【问题标题】:understanding memory leaks by MAT通过 MAT 了解内存泄漏
【发布时间】:2014-02-05 18:09:47
【问题描述】:

我是安卓编程新手。随着时间的推移,可能 android 应用程序的内存消耗会显着增加。通过 MAT 分析,可以看到 GC 根为Native Stack 的对象正在堆积。这些对象在本机代码中被引用为全局引用,但随着时间的推移正确释放,我还放置了日志以确保计数匹配。 关于native stack 的文档并不清楚,因为它只是指出:

本机代码中的输入或输出参数,例如用户定义的 JNI 代码或 JVM 内部代码。这通常是因为许多方法具有本机部分,并且作为方法参数处理的对象成为 GC 根。例如,用于文件/网络 I/O 方法或反射的参数。

我不太确定它说的是什么,问题出在哪里以及如何解决。任何提示都非常感谢。提前致谢。

【问题讨论】:

标签: java android memory-leaks android-ndk


【解决方案1】:

这个答案不会给你一个明确的解决方案,不是因为我不愿意,而是因为这是不可能的(如果不只是查看你的代码,而且非常了解你的代码,那就更难了)。但根据我的经验,我可以告诉你,这种内存泄漏不会仅仅由于直接引用的对象而发生——你声明的对象(并继续引用另一个类/对象)反过来又依赖于许多其他类等等,并且可能由于对同时引用其他实例的任何实例的处理不正确,您会看到内存泄漏。

调试内存泄漏通常是一项非常艰巨的工作,不仅因为正如我上面所说,它有时并不直接取决于您声明的内容,还因为找到解决方案可能并非易事。您可以做的最好的事情就是您似乎已经在做的事情:DDMS + HPROF。我不知道你有多少知识,虽然它不是一个通用的方法,但this link 在我的代码中发现内存泄漏帮助了我很多。

虽然看起来微不足道,但调试此类事情的最佳方法是逐步删除部分代码(总体而言,那些意味着使用其他类的实例的代码)并查看 HPROF 报告的变化。

---- 编辑----

这个关于 SO 的 question 是说明 GC 根源的一个很好的例子。

【讨论】:

  • +1 链接。但是你能帮我理解 GC root 作为 Native Stack 的含义吗?这是什么意思?
  • 据我了解,在某些情况下(大部分是可控的),您正在处理的某些对象可以从堆外访问。这基本上意味着您锁定了已分配且无法释放的层次结构的某些部分,但有时这并不意味着您直接引用它们。您引用的两个示例 JVM 和 JNI 分别引用了虚拟机并与其他语言交互 - 在某些情况下使用这些可能会导致它们成为 GC 根并成为巨大的内存泄漏生产者,因为它们可能不会被释放。
  • 在我的回答中添加了一个有用的链接。