要调试内存,首先需要获取HPROF文件,HPROF文件是MAT能识别的文件,HPROF文件存储的是特定时间点,java进程的内存快照。有不同的格式来存储这些数据,总的来说包含了快照被触发时java对象和类在heap中的情况。由于快照只是一瞬间的事情,所以heap dump中无法包含一个对象在何时、何地(哪个方法中)被分配这样的信息。
1、使用Android Studio获取HPROF文件(两种方法)
第一种:使用Android Studio同样可以导出对应的HPROF文件:
最新版本的Android Studio得在文件上右键转换成标准的HPROF文件,才可以在MAT中打开。
第二种:打开Android Device Monitor,类似于eclipse的DDMS
(我这里使用别人的DDMS图,和在Android Device Monitor的操作一样)
选择存储路径保存后就可以得到对应进程的HPROF文件。
-
如果是用 MAT Eclipse 插件获取的 Dump文件,不需要经过转换则可在MAT中打开,Adt会自动进行转换。
-
Android Studio需独立安装的MAT,并使用Android SDK自带的工具(hprof-conv 位置在sdk/platform-tools/hprof-conv)进行转换
hprof-conv xxx.xxx.xxx.hprof xxx.xxx.xxx.hprof
- 1
- 1
转换过后的.hprof文件即可使用MAT工具打开了。
查询内存泄露的地方
第一种方式:
1、在Histogram图中,在如图的位置输入进行查询,如:activity
选择with incominng references ,分析持有此类对象引用的外部对象
2、选择with incoming references 进入下图,分析这些持有引用的对象的GC路径,图中子菜单的两个选项,表示去除Phantom Ref(虚引用)和Weak Ref(弱引用),原因参考这里
3、逐个分析每个对象的GC路径是否正常
从这个路径可以看出是一个antiRadiationUtil工具类对象持有了MainActivity的引用导致MainActivity无法释放。此时就要进入代码分析此时antiRadiationUtil的引用持有是否合理(如果antiRadiationUtil持有了MainActivity的context导致节目退出后MainActivity无法销毁,那一般都属于内存泄露了)。
第二种方式:
怀疑某个对象存在泄露后,可以通过OQL来进一步证明。OQL可以通过查询语法,来查询具体的对象信息,主要使用的是查询某个类的实例信息。
语法为:
select * from instanceof Class
例如,查询类com.yunos.tv.launchersdk.view.component.ScreenContainer的所有实例:
select * from instanceof com.yunos.tv.launchersdk.view.component.ScreenContainer
- 1
- 2
- 3
- 1
- 2
- 3
得到的结果如图:
Class Name | Shallow Heap | Retained Heap |
---|---|---|
com.yunos.tv.launchersdk.view.component.ScreenContainer @ 0x443108e8 | 680 | 2,712 |
com.yunos.tv.launchersdk.view.component.ScreenContainer @ 0x42817648 | 680 | 16,289,472 |
图中说明com.yunos.tv.launchersdk.view.component.ScreenContainer这个类有两个实例,两个实例占用的内存大小分别为2,712和16,289,472。
如过实例的数量超出预期,说明存在内存泄露,如果实例所占内存的大小超出预期,说明这个实例内部的引用存在问题,可以进一步分析这个实例的具体信息。
MAT对比操作前后的hprof来定位内存泄露的根因所在
为查找内存泄漏,通常需要两个 Dump结果作对比,打开 Navigator History面板,将两个表的 Histogram结果都添加到 Compare Basket中去
1、第一个HPROF 文件(usingFile > Open Heap Dump ).
2、打开Histogram view.
3、在NavigationHistory view里 (如果看不到就从Window >show view>MAT- Navigation History ), 右击histogram然后选择Add to Compare Basket .
4、打开第二个HPROF 文件然后重做步骤2和3.
5、切换到Compare Basket view, 然后点击Compare the Results (视图右上角的红色”!”图标)。
6、分析对比结果
可以看出两个hprof的数据对象对比结果。
通过这种方式可以快速定位到操作前后所持有的对象增量,从而进一步定位出当前操作导致内存泄露的具体原因是泄露了什么数据对象。
转载:
https://mp.weixin.qq.com/s?__biz=MzA3NTYzODYzMg==&mid=400891536&idx=1&sn=0b6c629b0abe4a359d6552cd244c0c0c&scene=1&srcid=0303pbuNmzzdPnwQLozLrMip&pass_ticket=8HY76%2FaZXUVizdmMUJA7KW40UY8GIW54Sj85H1PLcNuzGxmipJ36D7AsqXOA%2BdRb#rd
http://www.jianshu.com/p/d8e247b1e7b2#