在我的应用程序的简化版本中,我有两个活动,A和B. Actvity A启动B,在一些工作之后B调用finish()。在大多数设备上使用Memory Analyzer工具(运行4.2的Galaxy Nexus,运行4.0.4的Droid 4和运行2.3.4的Droid 2)显示没有活动B的痕迹,这正是我的预期。
但是在运行4.1.1的三星S3上,MAT显示活动B对象仍然存在,原因是以下GC根路径(不包括弱/软引用):
Class Name | Shallow Heap | Retained Heap
-------------------------------------------------------------------------------------------------
com.myCo.myApp.ActivityB @ 0x42720818 | 264 | 3,280
|- <Java Local> java.lang.Thread @ 0x4271cf60 Thread-21941 Thread| 80 | 52,264
|- mOuterContext android.app.ContextImpl @ 0x426adf68 | 104 | 784
| '- mContext android.media.AudioManager @ 0x428e49a0 | 48 | 152
-------------------------------------------------------------------------------------------------
每次启动和停止活动B时,MAT都会显示活动B内存占用的另一个实例。我打开/关闭活动B的次数越多,logcat中报告的内存占用量就越大。通过MAT强制GC不会删除对活动B内存的引用。
我有三个问题。
为什么不同设备的内存/ GC行为会有所不同?
在S3上,操作系统最终是否会返回并且GC被搁置的活动B对象(换句话说,我应该不担心它,因为Android会在崩溃之前清理它)?
如果没有,Thread和AudioManager引用来自何处,以及如何清除它们?
感谢任何经验丰富的“泄密猎人”!
答案 0 :(得分:2)
更新:为了查看活动B留下的“搁浅”内存是否实际上是一个问题,我在活动A和B之间创建了一个循环:
--- A calls startActivityForResult() on B
--- B calls finish()
--- onActivityResult() in A calls B again, etc...
我让它飞行大约15k迭代,程序没有崩溃。所以即使这款手机上的JVM和操作系统版本(三星S3,4.1.1)在内存中留下了对B类的引用,即使在活动B调用finish()之后,它也会出现稍后的清理,如同在测试期间,B类的参考数量没有单调增加。
事实上,我在测试期间生成了几个堆转储,并且从未看到超过100个B类实例 - 而不是15k我希望看到没有其他清理。 logcat中的GC语句也显示内存使用同时向上和向上。尽管有大量的活动B调用。
我的结论是,我不应该担心在finish()调用之后堆转储中存在B类引用,因为看起来这个手机/ Android版本上使用的JVM会进行某种延迟清理。 / p>
注意:这是我根据我跑的测试推断的,所以如果有人知道不同请分享。谢谢!