在Android 应用程序开发和调试过程中 OOM (out of memory) 错误是个十分常见的问题,相信大多数应用开发者都遇到过,此类问题多半是程序运行一段时间后突然出错,而且出错后 Force Close, 因此不易查找原因。今日在这里分享下自己的一些经验。
从C++ 到 Java ,在面向对象编程的发展过程中,有了很大的进步。Java 引入了Garbage Collection 机制从而将程序开发者从繁琐的内存管理中解放出来,自此解决了C++中野指针和由于指向内存的指针丢失而造成的内存泄漏的问题。但是使用Java 就可随意使用内存不必担心内存泄漏的问题么? 显然不是。Garbage Collector 的职责是:1. 找到程序中不能再被访问的数据对象;2.释放这些对象占有的资源。所以看得出来Garbage Collector 回收内存的前提是对象已经不可访问(特殊类型的reference 不在内),逻辑上的内存泄漏(指向对象的引用没有被释放导致的内存泄漏)还是存在的。
解决这种逻辑上的内存泄漏关键是找到致使对象不能释放的引用链的始端,这个被称为GC Roots。熟悉java的朋友应该都知道有很多分析工具。因为本人是Android 开发对Java 不是很熟,所以只用过 Eclipse Memory Analyzer,在这里和大家分享一下。
1. Eclipse Memory Analyzer :
Open Help->Install New Software Add this URL http://download.eclipse.org/mat/1.1.0/update-site/
如果安装成功可以看到一个图标
3.分析原理 :
一个java heap dump 是某个时刻JVM中所有java 对象的一个镜像,而Eclipse Memory Analyzer 基于java heap dump 提供可视化的分析工具分析对象和引用存在情况。Eclipse Memory Analyzer 可以处理HPROF 格式的 heap dump.
4.Eclipse 可以将本地JVM 的heap dump 出来, 但是对于Android 则需要借助DDMS 将heap dump 出来。 如图(选择进程dump hprof file):
4.选择一下Leak Suspect Report
5.点选 Dominator Tree 查看对象列表
6.Dominator Tree 可以看到所有对象,最上面一行可以用正则,用来找到我们感兴趣的类和对象。
7.还可以对它们进行分组:
8.选择泄漏的对象,右键点击,可以容易的找到GC roots ,然后就容易分析这个引用为什么还指向这个对象致使它不能被回收了。
9.Eclipse Memory Analyzer 还有一个更强的功能就是对比不同的heap dumps, 试想如果你想对比几个不同时刻JVM 中java 对象的状态,你就会感觉这个工具特别好用。首先用DDMS dump 出heap,然后再Dominator Tree 视图 按包名分组,然后右击要分析的包,选择“Show Retained Set”
10.打开导航视图:(Window->showWindow->Other->Memory Analyzer Views->Navigation History)
11.在导航视图中,点击刚才选择的包,右击选择"Add to Compare Basket" ,然后即可以在Compare Basket 中看到了。
12.对几次不同的dump 重复进行上面的操作,看到Compare Basket 里面已经有了几次不同的记录,然后选择记录,右击,选择“Compare Tables with all set operations”
13.然后就可以看到对象对比了:
13.还可以选择百分比视图:
14.分析GC roots :
15. 参考资料: