内存分析工具MAT的使用

来源:互联网 发布:程序员需要学什么语言 编辑:程序博客网 时间:2024/06/09 15:54

1 内存泄漏的排查方法

Dalvik Debug Monitor Server (DDMS) 是 ADT插件的一部分,其中有两项功能可用于内存检查 :

· heap 查看堆的分配情况

· allocation tracker跟踪内存分配情况

DDMS 这两项功能有助于找到内存泄漏的操作行为。

Eclipse Memory Analysis Tools (MAT) 是一个分析 Java堆数据的专业工具,用它可以定位内存泄漏的原因。

工具地址 : https://www.eclipse.org/mat/

1.1 观察 Heap

· 运行程序,然后进入 DDMS管理界面,如下:

\

PS : 点击工具栏上的\来更新统计信息

点击右侧的 Cause GC 按钮或工具栏上的\即可查看当前的堆情况,如下:

\

主要关注两项数据:

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

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

· 查看操作前后的堆数据,看是否有内存泄漏 
对单一操作(比如添加页,删除页)进行反复操作,如果堆的大小一直增加,则有内存泄漏的隐患。

1.2 利用MAT分析内存堆

DDMS 可以将当前的内存 Dump成一个 hprof格式的文件,MAT 读取这个文件后会给出方便阅读的信息,配合它的查找,对比功能,就可以定位内存泄漏的原因。

· 获取 hprof文件 
点击工具栏上的\按钮,将内存信息保存成文件。 如果是用 MAT Eclipse 插件获取的 Dump文件,则不需要经过转换,Adt会自动进行转换然后打开。

· 转换 hprof文件 
DDMS Dump 出的文件要经过转换才能被 MAT识别,Android SDK提供了这个工具 hprof-conv (位于 sdk/tools下)

· ./hprof-conv xxx-a.hprof xxx-b.hprof

· 用 MAT打开转换后的 hprof文件

\

史上最难PHPer笔试题
【点击进入】
40分就能月薪过万! 2000多人测试,85%准确率

1.3 Histogram 查询

用的最多的功能是 Histogram,点击 Actions下的 Histogram项将得到 Histogram结果:

\

史上最难PHPer笔试题
【点击进入】
40分就能月薪过万! 2000多人测试,85%准确率

它按类名将所有的实例对象列出来,可以点击表头进行排序,在表的第一行可以输入正则表达式来匹配结果 :

\

史上最难PHPer笔试题
【点击进入】
40分就能月薪过万! 2000多人测试,85%准确率

在某一项上右键打开菜单选择 list objects ->with incoming refs 将列出该类的实例:

\

史上最难PHPer笔试题
【点击进入】
40分就能月薪过万! 2000多人测试,85%准确率

它展示了对象间的引用关系,比如展开后的第一个子项表示这个 HomePage(0x420ca5b0)被 HomePageContainer(0x420c9e40)中的 mHomePage属性所引用.

快速找出某个实例没被释放的原因,可以右健 Path to GC Roots-->exclue all phantom/weak/soft etc. reference :

\

得到的结果是:

\

从表中可以看出 PreferenceManager -> … ->HomePage这条线路就引用着这个 HomePage实例。用这个方法可以快速找到某个对象的 GC Root,一个存在 GC Root的对象是不会被 GC回收掉的.

1.4 Histogram 对比

为查找内存泄漏,通常需要两个 Dump结果作对比,打开 Navigator History面板,将两个表的 Histogram结果都添加到 Compare Basket中去 :

\

添加好后,打开 Compare Basket面板,得到结果:

\

点击右上角的 ! 按钮,将得到比对结果:

\

注意,上面这个对比结果不利于查找差异,可以调整对比选项:

\

再把对比的结果排序,就可得到直观的对比结果:

\

也可以对比两个对象集合,方法与此类似,都是将两个 Dump结果中的对象集合添加到Compare Basket中去对比。找出差异后用 Histogram查询的方法找出 GC Root,定位到具体的某个对象上。

1.5 例子

举例一个典型的分析内存泄漏的过程:

1. 使用 Heap查看当前堆大小为 23.00M

2. 添加一个页后堆大小变为 23.40M

3. 将添加的一个页删除,堆大小为 23.40M

4. 多次操作,结果仍相似,说明添加/删除页存在内存泄漏 (也应注意排除其它因素的影响)

5. Dump 出操作前后的 hprof 文件 (1.hprof,2.hprof),用 mat打开,并得到 histgram结果

6. 使用 HomePage字段过滤 histgram结果,并列出该类的对象实例列表,看到两个表中的对象集合大小不同,操作后比操作前多出一个 HomePage,说明确实存在泄漏

7. 将两个列表进行对比,找出多出的一个对象,用查找 GC Root的方法找出是谁串起了这条引用线路,定位结束

PS :

· 很多时候堆增大是 Bitmap引起的,Bitmap在 Histogram中的类型是 byte [],对比两个 Histogram中的 byte[] 对象就可以找出哪些 Bitmap有差异

· 多使用排序功能,对找出差异很有用

2 内存泄漏的原因分析

总结出来只有一条: 存在无效的引用! 
良好的模块设计以及合理使用设计模式有助于解决此问题。

3 Tips

· 使用 android:largeHeap="true"标记 (API Level >= 11) 
在 AndroidManifest.xml中的 Application节点中声明即可分配到更大的堆内存, android:largeHeap标记在 Android系统应用中也有广泛的应用 ,比如 Launcher, Browser这些内存大户上均有使用.

4 参考

· DDMS 官方教程 http://developer.android.com/tools/debugging/ddms.html

· MAT 下载 http://www.eclipse.org/mat/downloads.php

· MAT 使用 http://android-developers.blogspot.tw/2011/03/memory-analysis-for-android.html

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 高三孩子考试时慌乱老粗心怎么办 助班面试你的学生不喜欢你怎么办 上三年级的小孩不愿做作业怎么办 快一年了孩子上幼儿园总哭怎么办 宝宝吃多了吐了很多怎么办 一岁宝宝只吃母乳不吃辅食怎么办 孩子平常考得好正式考不好怎么办 平常成绩好期末却考不好怎么办 初中生去国外上学国内的学校怎么办 孩子在学校不受老师的重视怎么办 孩子上二年级了不爱学习怎么办 接别人的班被学生讨厌怎么办 孩子在学校老师打孩子家长怎么办? 宝宝不听话我老忍不住打他怎么办 两岁宝宝断母乳不愿意喝奶粉怎么办 2岁半的宝宝叛逆不听话怎么办? 2岁半宝宝说什么不听话怎么办? 误把脱毛膏当牙膏用了刷牙怎么办 儿子1岁5个月了不说话怎么办 两岁小儿不会说话和智商低怎么办 宝宝不会说话教他说他不愿意怎么办 25个月宝宝不愿意学说话怎么办 老师说小孩在幼儿园老是说话怎么办 在外留学想领养一个外国小孩怎么办 三岁半的宝宝想去美国上学怎么办 农村新房边的老老祖坟不搬怎么办 倒西太阳晒的房子夏天很热怎么办 客厅壁纸用的浅灰色影视墙怎么办 我喜欢玩手机游戏妈妈很生气怎么办 家里墙上有很多白色的虫子怎么办 3岁半宝宝学数字学不会怎么办 小孩子读一年级拼音读不好要怎么办 4个月的婴儿恶心干呕怎么办 生了小孩后胆汁酸偏高怎么办 9个月宝宝吃盐了怎么办 两个月宝宝母乳拉大便太稀怎么办呀 两个月的宝宝不拉大便怎么办 两个月宝宝五天没拉大便怎么办 4个月宝宝不拉大便怎么办 2个月宝宝3天没拉大便怎么办 宝宝拉不出大便老是憋的哭怎么办