1 概述
mat是用于分析java内存泄露的工具之一。
2 生成hprof
打开Android Device Monitor(或者Eclipse),找到DDMS,如下。
- 第一个图标,是debug 用于调试
- 第二个图标 update heap 更新堆内存
- 第三个图标 Dump HPROF file 用来将堆内存生成HPROF文件。
- 第四个图标 Gause GC 用于触发GC回收内存,一般在生成HPROF前调用,用于去掉可以被GC回收的内存,减少分析的内存大小。
到此,hprof文件已经生成,我们可以进行下一步,使用mat分析hprof了。
注:DDMS Dump 出的文件要经过转换才能被 MAT识别,Android SDK提供了这个工具 hprof-conv (位于 sdk/tools下)
./hprof-conv xxx-a.hprof xxx-b.hprof
3 mat
用MAT打开转换后的 hprof文件。
Histogram 查询
点击 Actions下的 Histogram项将得到 Histogram结果:
按类名将所有的实例对象列出来,可以点击表头进行排序,在表的第一行可以输入正则表达式来匹配结果 :
在某一项上右键打开菜单选择 list objects ->with incoming refs 将列出该类的实例:
它展示了对象间的引用关系,比如展开后的第一个子项表示这个 HomePage(0x420ca5b0)被 HomePageContainer(0x420c9e40)中的 mHomePage属性所引用.
快速找出某个实例没被释放的原因,可以右健 Path to GC Roots–>exclue all phantom/weak/soft etc. reference :
从表中可以看出 PreferenceManager -> … ->HomePage这条线路就引用着这个 HomePage实例。用这个方法可以快速找到某个对象的 GC Root,一个存在 GC Root的对象是不会被 GC回收掉的.
- Histogram 对比
为查找内存泄漏,通常需要两个 Dump结果作对比,打开 Navigator History面板,将两个表的 Histogram结果都添加到 Compare Basket中去 :
添加好后,打开 Compare Basket面板,得到结果:
点击右上角的 ! 按钮,将得到比对结果:
注意,上面这个对比结果不利于查找差异,可以调整对比选项:
再把对比的结果排序,就可得到直观的对比结果:
也可以对比两个对象集合,方法与此类似,都是将两个 Dump结果中的对象集合添加到Compare Basket中去对比。找出差异后用 Histogram查询的方法找出 GC Root,定位到具体的某个对象上。
- 优化
使用 android:largeHeap=”true”标记 (API Level >= 11)
在 AndroidManifest.xml中的 Application节点中声明即可分配到更大的堆内存, android:largeHeap标记在 Android系统应用中也有广泛的应用 ,比如 Launcher, Browser这些内存大户上均有使用.