内存泄露之排查篇

转载:
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#

Android Device Monitor分析heap

Android Device Monitor分析heap的总内存占用大小来初步判断是否存在泄露

  Android Device Monitor,类似于eclipse的DDMS
  1. 在Devices 中,点击要监控的程序。
  2. 点击Devices视图界面中最上方一排图标中的“Update Heap”
  3. 点击Heap视图
  4. 点击Heap视图中的“Cause GC”按钮
  5. 到此为止需检测的进程就可以被监视。

Heap视图中部有一个Type叫做data object,即数据对象,也就是我们的程序中大量存在的类类型的对象。在data object一行中有一列是“Total Size”,其值就是当前进程中所有Java数据对象的内存总量,一般情况下,这个值的大小决定了是否会有内存泄漏。

可以这样判断:
进入某应用,不断的操作该应用,同时注意观察data object的Total Size值,正常情况下Total Size值都会稳定在一个有限的范围内,也就是说由于程序中的的代码良好,没有造成对象不被垃圾回收的情况。

所以说虽然我们不断的操作会不断的生成很多对象,而在虚拟机不断的进行GC的过程中,这些对象都被回收了,内存占用量会会落到一个稳定的水平;反之如果代码中存在没有释放对象引用的情况,则data object的Total Size值在每次GC后不会有明显的回落。随着操作次数的增多Total Size的值会越来越大,直到到达一个上限后导致进程被杀掉。

MAT分析hprof来定位内存泄露的原因所在

要调试内存,首先需要获取HPROF文件,HPROF文件是MAT能识别的文件,HPROF文件存储的是特定时间点,java进程的内存快照。有不同的格式来存储这些数据,总的来说包含了快照被触发时java对象和类在heap中的情况。由于快照只是一瞬间的事情,所以heap dump中无法包含一个对象在何时、何地(哪个方法中)被分配这样的信息。

1、使用Android Studio获取HPROF文件(两种方法)

第一种:使用Android Studio同样可以导出对应的HPROF文件:

内存泄露之排查篇_第1张图片

最新版本的Android Studio得在文件上右键转换成标准的HPROF文件,才可以在MAT中打开。

第二种:打开Android Device Monitor,类似于eclipse的DDMS

内存泄露之排查篇_第2张图片
(我这里使用别人的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 

转换过后的.hprof文件即可使用MAT工具打开了。

2、Android Studio的同学使用MAT独立软件打开

3、在Histogram图中,在如图的位置输入进行查询,如:activity
选择with incominng references ,分析持有此类对象引用的外部对象

这里写图片描述
4、选择with incoming references 进入下图,分析这些持有引用的对象的GC路径,图中子菜单的两个选项,表示去除Phantom Ref(虚引用)和Weak Ref(弱引用),原因参考这里

内存泄露之排查篇_第3张图片

5、逐个分析每个对象的GC路径是否正常
这里写图片描述

从这个路径可以看出是一个antiRadiationUtil工具类对象持有了MainActivity的引用导致MainActivity无法释放。此时就要进入代码分析此时antiRadiationUtil的引用持有是否合理(如果antiRadiationUtil持有了MainActivity的context导致节目退出后MainActivity无法销毁,那一般都属于内存泄露了)。

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张图片

4、打开第二个HPROF 文件然后重做步骤2和3.

5、切换到Compare Basket view, 然后点击Compare the Results (视图右上角的红色”!”图标)。

这里写图片描述

6、分析对比结果

内存泄露之排查篇_第5张图片

可以看出两个hprof的数据对象对比结果。
通过这种方式可以快速定位到操作前后所持有的对象增量,从而进一步定位出当前操作导致内存泄露的具体原因是泄露了什么数据对象。

你可能感兴趣的:(android,内存,heap,内存泄露)