使用mat进行内存分析的方法

来源:互联网 发布:keil软件的使用方法 编辑:程序博客网 时间:2024/05/22 08:21

安卓app内存分析方法:

工具:ddms+mat

内存泄漏指的是那些程序不再使用的对象无法被GC识别,这样就导致这个对象一直留在内存当中,占用了宝贵的内存空间。

如果这个对象有个引用指向一个包括很多其他对象的集合,就会导致这些对象都不会被垃圾回收。


GC全称是Garbage Collection,也就是所谓的垃圾回收。Android系统会在适当的时机触发GC操作,一旦进行GC操作,就会将一些不再使用的对象进行回收

GC流程:


  • 上图当中,每个蓝色的圆圈就代表一个内存当中的对象,而圆圈之间的箭头就是它们的引用关系
  • 这些对象有些是处于活动状态的,而有些就已经不再被使用了
  • GC操作会从一个叫作Roots的对象开始检查,所有它可以访问到的对象就说明还在使用当中,应该进行保留,而其它的对象就表示已经不再被使用了,如下图所示:

可以看到,目前所有黄色的对象仍然会被系统继续保留,而蓝色的对象就会在GC操作当中被系统回收掉了,这大概就是Android系统一次简单的GC流程


内存泄漏分析基础思路:找到哪个类的对象引用没有被释放,找到没有被释放的原因。

   1. 把app使用的heap dump下来。

   2. 使用MAT找出内存占用超出预期的嫌疑对象。

   3. 根据情况,分析嫌疑对象和其他对象的引用关系。

4. 分析程序的源代码,找出嫌疑对象数量过多的原因。

以下主要通过Allocated检查,常驻activity检测,常驻对象的检测, bitmap尺寸检查,线程泄漏检测5个角度分析app的内存泄漏风险。

 

一.  Allocated检查方法

1.    启动ddms,选择进程,点击绿色的桶

2.    打开heap视图,点击cause gc,操作新功能,在操作的过程中观察Allocated的值峰值


其中,Heap Size 表示堆的大小,当资源增加,当前堆的空余空间不够时,系统会增加堆的大小,若超过上限 (例如 64M,视平台和具体机型而定)则会被杀掉。

Allocated表示堆中已分配的大小,这是应用程序实际占用的内存大小,资源回收后,此项数据会变小

标准:Allocated的值一般不能超过内存阀值的60%。

 

3.    内存阀值有多大呢?不同的手机有不同的内存阀值,查看方法如下:

打开CMD,进入adb shell,输入cat /system/build.prop | grepheap,你会看到如下情况:


阀值是heapsize或heapgrowthlimit,选择优先级为:heapsize<heapgrowthlimit(注意:如果app设置了largeHeap,两个值都存在的情况,应选择heapsize)。

查看工程中的AndroidMenifest.xml文件,查看largeHeap配置项,如果largeHeap为true,则表明app设置了largeHeap

4.    data object,即数据对象,也就是我们的程序中大量存在的类类型的对象。在data object一行中有一列是“TotalSize”,其值就是当前进程中所有Java数据对象的内存总量,一般情况下,这个值的大小决定了是否会有内存泄漏。可以这样判断

a) 不断的操作当前应用,同时注意观察dataobject的TotalSize值

b) 正常情况下TotalSize值都会稳定在一个有限的范围内,也就是说由于程序中的的代码良好,没有造成对象不被垃圾回收的情况,所以说虽然我们不断的操作会不断的生成很多对象,而在虚拟机不断的进行GC的过程中,这些对象都被回收了,内存占用量会会落到一个稳定的水平

c) 反之如果代码中存在没有释放对象引用的情况,则dataobject的TotalSize值在每次GC后不会有明显的回落,随着操作次数的增多TotalSize的值会越来越大,直到到达上限后导致进程被kill掉

 

二.  常驻activity检测方法

1、反复多次操作新功能,退出新功能界面后,反复gc后,抓dump


2、dump抓到后会自动在eclipse里展示出来,接下来是分析是否有activity泄漏。

   通过关键字将相关activity过滤出来

3、有activity泄漏的现象

若已经退出新功能,但还存在与新功能相关的activity,则存在activity泄漏。

4、有些可疑的activity,需要确认下这些可疑的activity是否最终会被系统回收

操作方法:

   右键activity -> Path To GC Roots -> exclude weak/soft renferences,可进一步筛选出跟程序相关的所有有内存泄露的类

 

三.  常驻对象的检测方法

1、进入新功能前,gc后dump

2、进入新功能

3、退出新功能,gc后dump

4、点击widows->show view 选择添加navigation history。将2个内存快照的Histogarm添加到compare basket(在navigation history右击Histogarm,选择add to compare basket),点击Compare the Results(视图右上角的红色"!"图标)

 

 

过滤新增类,看是否存在new的对象而没有gc的,这种就可能是常驻对象

 

四.  Bitmap尺寸测试方法

进入新功能,gc后抓dump,然后使用Inspector查看(Window >ShowView > Other.. > Inspector)

进入过滤bitmap后,查看bitmap的宽高,看是否有大于手机屏幕分辨率的bitmap。


五.  线程泄漏检测方法

选择进程后,点击updatethreads按钮,在Thead视图中可以看到当前进程中的线程,如果某个功能有线程泄漏,则反复操作该功能时线程就会一直增长。





0 0
原创粉丝点击