【问题标题】:Does my Android program have a memory leak?我的 Android 程序是否存在内存泄漏?
【发布时间】:2013-12-27 20:38:22
【问题描述】:

我知道如果没有实际代码,这似乎无法确定,但请多多包涵。我认为可以从症状中确定一些东西。

我有一个层次结构浏览器,其中层次结构的每个级别都由其自己的活动显示。如果您检查层次结构的太多分支,它将引发OutOfMemoryError 异常。这听起来像是内存泄漏,但随便看看代码并没有发现任何明显的东西,所以我想在进行更彻底的调查之前对 Java 和 Android 的某些方面进行一些澄清。

首先,我可以依赖未使用的活动在OutOfMemoryError 被抛出之前进行垃圾收集吗?如果不是这种情况,我会认为这是一种奇怪的行为,但它可以解释我遇到的一切。

其次,Dalvik 垃圾收集器可以收集循环引用吗?我想我没有,但如果没有,我会知道在我的代码中寻找它。

我知道有办法在 Android 应用程序中通过创建对在程序生命周期中存在的地方的事物的引用来泄漏内存,但我不认为我正在这样做。例如,我没有以编程方式创建任何 UI 控件,也没有将当前活动作为 Context 传递给任何东西。

最后,我最近从未注意到这个错误,自从它首次创建以来唯一发生的变化是 Android 版本从某种风味的 Jelly Bean 升级为 KitKat。

任何帮助将不胜感激。谢谢!

【问题讨论】:

  • 如果您不调用finish() 或您的活动,那么您不能依赖它们被GCed,因为Android 负责它们的生命周期(onCreate()onResume())。移动到后台的活动,你没有finish(),可能会或可能不会被释放,因此有资格获得 GC。根据您的描述,我建议覆盖后退键并完成您的活动是要走的路。综上所述,当堆使用接近 OOM 条件时,Android 肯定会杀死你的活动,所以是的,我怀疑你正在泄漏一些东西。位图?

标签: java android memory-leaks


【解决方案1】:

首先,我可以依赖未使用的活动在抛出 OutOfMemoryError 之前进行垃圾回收吗?

尽管普遍认为,答案是否定的。您可以用活动填充内存,直到引发错误,Android 既不会在后台堆栈中 destroy any activities,也不会在 GC 期间收集这些活动。

系统有一个选项可以完成后台堆栈中的活动,但它在 2011 年被禁用。现在,如果系统内存不足,Android 只会终止整个进程。前台应用程序很可能会达到每个应用程序的堆限制,因为系统会避免杀死它,并且可能有大量可用内存供其他应用程序使用。

为什么不对活动进行 GC?所有正在运行的活动都存储在 ActivityThread 类中(它执行与系统的所有交互并处理活动的生命周期事件),因此它们不符合垃圾回收条件。它们只有在被摧毁后才会从这里移除。

其次,Dalvik 垃圾收集器能否收集循环引用?

是的,它可以,就像常规 JVM 的垃圾收集器一样。否则它不会与 Java 兼容。

您可以使用Memory Analyzer tool and other techniques 检查所有内存的去向。这些工具可以向您显示堆上的对象以及阻止它们被收集的原因。

我可以建议您在单个活动而不是多个活动中使用Fragments。片段具有回调,可用于在片段离开屏幕(返回堆栈)时释放视图层次结构。

【讨论】:

  • 即使对于不在后台的活动,第一个演员也是真的吗?例如,我的层次结构通常很浅,所以假设我们有一个根节点 A 和两个子节点 B 和 C。如果我启动一个活动 A(显示节点 A)然后选择 B,返回到 A 然后查看 C , 即使我内存不足,B 也不会被 GC 处理?
  • 不,一旦 Activity 被销毁,它就有资格获得 GC。您能否使用内存分析器检查堆转储以找到对已破坏活动的引用?
  • 我可以,但显然没有什么是泄漏。应该销毁的活动和根活动之间存在一些不同的引用,例如 PhoneWindow、PhoneLayoutInflater、FragmentManagerImpl、ViewStub、FrameLayout、RelativeLayout、GridView、ContextImpl、app.Activity。可能还有其他人,但我不能仅仅通过观察就能看到它们。这些听起来很熟悉吗?
  • 您提到的类通常将活动引用为上下文 - 实际上,活动拥有这些,因此其他东西正在持有活动。您是否尝试过对应按照developer.android.com/tools/debugging/… 中所述收集的活动使用“显示 GC 根路径”?通常,持有引用的内容很快就会变得很明显。
  • 是的,所有线程都已启动并且它们没有循环,因此它们保证完成。实际上,我似乎有这个问题:stackoverflow.com/questions/6445052/… 但它没有解决方案。
猜你喜欢
  • 2012-06-19
  • 1970-01-01
  • 2013-05-31
  • 1970-01-01
  • 2011-01-29
  • 2011-05-08
  • 1970-01-01
  • 2011-12-25
相关资源
最近更新 更多