Google I/O中的Android内存泄漏示例

11

我刚看了Google IO的“内存管理 for Android”视频。幻灯片可以在这里找到http://dubroy.com/memory_management_for_android_apps.pdf,内存泄漏例子在第36页。

我不明白为什么方向改变后会导致内存泄漏。我理解泄漏是一个内部类并引用外部类。同时我也理解静态变量“leak”引用“Leaky”对象,因此引用整个activity。我认为这很特别,因为它有一个静态关键字。静态变量具有一定的内存,可能不会被垃圾回收(至少在应用程序运行时)?!?

那么,在方向改变时发生了什么?创建了一个新的活动实例,调用了activities的onCreateleak==null是false。泄漏仍然指向“旧”活动。这是一种泄漏。旧活动无法被回收,对吧?

为什么每次方向改变都会增加内存使用?根据我的(错误)理解,我会假设只有第一个活动无法被垃圾回收。由于它们没有被静态变量“泄漏”引用,因此可以回收会发生方向改变而创建的其他活动。

然而..显然..我是完全错误的!


这个有用吗?如果可以的话,请点个赞 :) - Walter K
我认为你认为activity的销毁等同于垃圾回收。我已经添加了一个答案,试图解释正在发生的事情。基本上,这是因为在新创建的activity中,泄漏等于null。关于原因,请阅读我的答案。 - iheanyi
2个回答

2
一篇经典的关于屏幕旋转导致Context内存泄漏的解释,来自Google博客。我认为你已经接近答案了,注意到了内部类对外部类的静态引用。

是的,我之前看过了。实际上它是一样的,作者说“它泄漏了第一个活动”。这就是我上面描述的行为。对我来说,第一个活动泄漏是明显的。但是_只有_第一个。之后的方向更改不应再增加堆,也不应再发生泄漏。但是在我发布的视频中,堆似乎随着每次方向更改而增加(从9mb到12到15mb,从28分钟开始)。好吧,我很快就要测试这个了。 - 207
我的理解是,每次改变方向时,活动都会丢失,但不会被回收。当你从横屏切换回竖屏时,你将无法获得最初的上下文。 - Walter K
是的,你不会得到你的初始上下文。但为什么每次都是这样呢?静态变量只引用第一个活动。 - 207
在第一次创建活动后,静态变量始终不为 null。因此,静态变量将始终引用第一个活动。 - 207

1
您不理解是因为您犯了一个关键性的错误。在新创建的活动中,leak == null 为真。leak 不再指向“旧”活动。

为什么呢?您可能会问,我以为 leak 是静态的。好吧……

第一次创建活动时,leak 为 null,然后 onCreate() 方法被调用,leak 现在引用了一个 Leaky 对象。如果我创建该活动的更多实例,则它们的 leak 不会为 null,并引用同一个对象。

但是,当您翻转方向时会发生什么呢?活动被销毁。因此,不存在现有的活动对象实例。Android 然后创建一个新的活动,在其中 leak 为 null(因为 Android 认为不存在该活动的其他实例)。

但是,对于垃圾收集器来说,确实有人持有对已销毁活动的引用,即其内部的 Leaky 类。因此,它不会释放该内存。因此,随着您继续更改方向,您将继续泄漏活动所需的内存。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接