Android 中使用内存监测工具Heap,及内存分析工具 MAT

无论怎么小心,想完全避免bad code是不可能的,此时就需要一些工具来帮助我们检查代码中是否存在会造成内存泄漏的地方。Android tools中的DDMS就带有一个很不错的内存监测工具Heap(这里我使用eclipse的ADT插件,并以真机为例,在模拟器中的情况类似)。用Heap监测应用进程使用内存情况的步骤如下:

1. 启动eclipse后,切换到DDMS透视图,并确认Devices视图、Heap视图都是打开的;

2. 将手机通过USB链接至电脑,链接时需要确认手机是处于“USB调试”模式,而不是作为“Mass Storage”;

3. 链接成功后,在DDMS的Devices视图中将会显示手机设备的序列号,以及设备中正在运行的部分进程信息;

4. 点击选中想要监测的进程,比如system_process进程;

5. 点击选中Devices视图界面中最上方一排图标中的“Update Heap”图标;

6. 点击Heap视图中的“Cause GC”按钮;

7. 此时在Heap视图中就会看到当前选中的进程的内存使用量的详细情况

如图所示

说明:

a) 点击“Cause GC”按钮相当于向虚拟机请求了一次gc操作;

b) 当内存使用信息第一次显示以后,无须再不断的点击“Cause GC”,Heap视图界面会定时刷新,在对应用的不断的操作过程中就可以看到内存使用的变化;

c) 内存使用信息的各项参数根据名称即可知道其意思,在此不再赘述。

如何才能知道我们的程序是否有内存泄漏的可能性呢。这里需要注意一个值:Heap视图中部有一个Type叫做data object,即数据对象,也就是我们的程序中大量存在的类类型的对象。在data object一行中有一列是“Total Size”,其值就是当前进程中所有Java数据对象的内存总量,一般情况下,这个值的大小决定了是否会有内存泄漏。可以这样判断:

a) 不断的操作当前应用,同时注意观察data object的Total Size值;

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

c) 反之如果代码中存在没有释放对象引用的情况,则data object的Total Size值在每次GC后不会有明显的回落,随着操作次数的增多Total Size的值会越来越大,

直到到达一个上限后导致进程被kill掉。

d) 此处已system_process进程为例,在我的测试环境中system_process进程所占用的内存的data object的Total Size正常情况下会稳定在2.2~2.8之间,而当其值超过3.55后进程就会被kill。

总之,使用DDMS的Heap视图工具可以很方便的确认我们的程序是否存在内存泄漏的可能性。

内存分析工具 MAT(Memory Analyzer Tool)

如果使用DDMS确实发现了我们的程序中存在内存泄漏,那又如何定位到具体出现问题的代码片段,最终找到问题所在呢?如果从头到尾的分析代码逻辑,那肯定会把人逼疯,特别是在维护别人写的代码的时候。这里介绍一个极好的内存分析工具 -- Memory Analyzer Tool(MAT)。

MAT是一个Eclipse插件,同时也有单独的RCP客户端。官方下载地址、MAT介绍和详细的使用教程请参见:www.eclipse.org/mat,在此不进行说明了。另外在MAT安装后的帮助文档里也有完备的使用教程。在此仅举例说明其使用方法。我自己使用的是MAT的eclipse插件,使用插件要比RCP稍微方便一些。

使用MAT进行内存分析需要几个步骤,包括:生成.hprof文件、打开MAT并导入.hprof文件、使用MAT的视图工具分析内存。以下详细介绍。

(一) 生成.hprof文件

生成.hprof文件的方法有很多,而且Android的不同版本中生成.hprof的方式也稍有差别,我使用的版本的是2.1,各个版本中生成.prof文件的方法请参考:

http://android.git.kernel.org/?p=platform/dalvik.git;a=blob_plain;f=docs/heap-profiling.html;hb=HEAD。

1. 打开eclipse并切换到DDMS透视图,同时确认Devices、Heap和logcat视图已经打开了;

2. 将手机设备链接到电脑,并确保使用“USB 调试”模式链接,而不是“Mass Storage“模式;

3. 链接成功后在Devices视图中就会看到设备的序列号,和设备中正在运行的部分进程;

4. 点击选中想要分析的应用的进程,在Devices视图上方的一行图标按钮中,同时选中“Update Heap”和“Dump HPROF file”两个按钮;

5. 这是DDMS工具将会自动生成当前选中进程的.hprof文件,并将其进行转换后存放在sdcard当中,如果你已经安装了MAT插件,那么此时MAT将会自动被启用,并开始对.hprof文件进行分析;

注意:第4步和第5步能够正常使用前提是我们需要有sdcard,并且当前进程有向sdcard中写入的权限(WRITE_EXTERNAL_STORAGE),否则.hprof文件不会被生成,在logcat中会显示诸如 ERROR/dalvikvm(8574): hprof: can‘t open /sdcard/com.xxx.hprof-hptemp: Permission denied 的信息。

如果我们没有sdcard,或者当前进程没有向sdcard写入的权限(如system_process),那我们可以这样做:

6. 在当前程序中,例如framework中某些代码中,可以使用android.os.Debug中的:

public static void dumpHprofData(String fileName) throws IOException

方法,手动的指定.hprof文件的生成位置。例如:

xxxButton.setOnClickListener(new View.OnClickListener() {

public void onClick(View view) {

android.os.Debug.dumpHprofData("/data/temp/myapp.hprof");

... ...

}

}

上述代码意图是希望在xxxButton被点击的时候开始抓取内存使用信息,并保存在我们指定的位置:/data/temp/myapp.hprof,这样就没有权限的限制了,而且也无须用sdcard。但要保证/data/temp目录是存在的。这个路径可以自己定义,当然也可以写成sdcard当中的某个路径。

(二) 使用MAT导入.hprof文件

1. 如果是eclipse自动生成的.hprof文件,可以使用MAT插件直接打开(可能是比较新的ADT才支持);

2. 如果eclipse自动生成的.hprof文件不能被MAT直接打开,或者是使用android.os.Debug.dumpHprofData()方法手动生成的.hprof文件,则需要将.hprof文件进行转换,转换的方法:

例如我将.hprof文件拷贝到PC上的/ANDROID_SDK/tools目录下,并输入命令hprof-conv xxx.hprof yyy.hprof,其中xxx.hprof为原始文件,yyy.hprof为转换过后的文件。转换过后的文件自动放在/ANDROID_SDK/tools目录下。OK,到此为止,.hprof文件处理完毕,可以用来分析内存泄露情况了。

3. 在Eclipse中点击Windows->Open Perspective->Other->Memory Analyzer,或者打Memory Analyzer Tool的RCP。在MAT中点击File->Open File,浏览并导入刚刚转换而得到的.hprof文件。

(三) 使用MAT的视图工具分析内存

导入.hprof文件以后,MAT会自动解析并生成报告,点击Dominator Tree,并按Package分组,选择自己所定义的Package类点右键,在弹出菜单中选择List objects->With incoming references。这时会列出所有可疑类,右键点击某一项,并选择Path to GC Roots -> exclude weak/soft references,会进一步筛选出跟程序相关的所有有内存泄露的类。据此,可以追踪到代码中的某一个产生泄露的类。

MAT的界面如下图所示。

具体的分析方法在此不做说明了,因为在MAT的官方网站和客户端的帮助文档中有十分详尽的介绍。

了解MAT中各个视图的作用很重要,例如www.eclipse.org/mat/about/screenshots.php中介绍的。

总之使用MAT分析内存查找内存泄漏的根本思路,就是找到哪个类的对象的引用没有被释放,找到没有被释放的原因,也就可以很容易定位代码中的哪些片段的逻辑有问题了。

原文地址:http://blog.csdn.net/qeqeqe236/article/details/7338608

时间: 2024-10-10 17:21:47

Android 中使用内存监测工具Heap,及内存分析工具 MAT的相关文章

Java Heap dump文件分析工具jhat简介

jhat 是Java堆分析工具(Java heap Analyzes Tool). 在JDK6u7之后成为标配. 使用该命令需要有一定的Java开发经验,官方不对此工具提供技术支持和客户服务. 用法: jhat [ options ] heap-dump-file 参数: options 可选命令行参数,请参考下面的 Options heap-dump-file 要查看的二进制Java堆转储文件(Java binary heap dump file). 如果某个转储文件中包含了多份 heap d

android中使用jni对字符串加解密实现分析

android中使用jni对字符串加解密实现分析 最近项目有个需求,就是要对用户的敏感信息进行加密处理,比如用户的账户密码,手机号等私密信息.在java中,就对字符串的加解密我们可以使用AES算法加密字符串,使用它的好处就不必多说了,但我们又知道android的源代码是可以被反编译的,所以使用纯Java方式的AES加密是不安全的,所以想到了使用android中的jni来对字符串加解密处理,它会产生一个.so文件,更重要的是它通过C/C++代码实现,所以安全行比较高,它可以被反编译成机器码,但几乎

Android中Preference的使用以及监听事件分析

> 在Android系统源码中,绝大多数应用程序的UI布局采用了Preference的布局结构,而不是我们平时在模拟器中构建应用程序时使用的View布局结构,例如,Setting模块中布局.当然,凡事都有例外,FMRadio应用程序中则使用了View布局结构(可能是该应用程序是marvel公司提供的,如果由google公司做,那可说不准).归根到底,Preference布局结构和View的布局结构本质上还是大同小异,Preference的优点在于布局界面的可控性和高效率以及可存储值的简洁性(每个

Android中实现IPC的几种方式详细分析及比较

1.使用Bundle   ----> 用于android四大组件间的进程间通信 android的四大组件都可使用Bundle传递数据  所以如果要实现四大组件间的进程间通信 完全可以使用Bundle来实现 简单方便 2.使用文件共享  ---->用于单线程读写 这种方式在单线程读写的时候比较好用 如果有多个线程并发读写的话需要限制线程的同步读写 另外 SharePreference是个特例  它底层基于xml实现  但是系统对它的读写会基于缓存,也就是说再多进程模式下就变得不那么可靠了,有很大

Android中View绘制流程以及invalidate()等相关方法分析

前言: 本文是我读<Android内核剖析>第13章----View工作原理总结而成的,在此膜拜下作者 .同时真挚地向渴望了解 Android 框架层的网友,推荐这本书,希望你们能够在Android开发里学到更多的知识 . 整个View树的绘图流程是在ViewRoot.java类的performTraversals()函数展开的,该函数做的执行过程可简单概况为 根据之前设置的状态,判断是否需要重新计算视图大小(measure).是否重新需要安置视图的位置(layout).以及是否需要重绘 (d

Android中View绘制流程以及invalidate()等相关方法分析(转载的文章,出处在正文已表明)

转载请注明出处:http://blog.csdn.net/qinjuning 前言: 本文是我读<Android内核剖析>第13章----View工作原理总结而成的,在此膜拜下作者 .同时真挚地向渴望了解 Android 框架层的网友,推荐这本书,希望你们能够在Android开发里学到更多的知识 . 整个View树的绘图流程是在ViewRoot.java类的performTraversals()函数展开的,该函数做的执行过程可简单概况为 根据之前设置的状态,判断是否需要重新计算视图大小(mea

Android中屏幕密度和图片大小的关系分析

转发:http://blog.csdn.net/singwhatiwanna/article/details/19139013 前言 Android中支持许多资源,包括图片(Bitmap),对应于bitmap的文件夹是drawable,除了drawable,还有drawable-ldpi.drawable-mdpi.drawable-hdpi.drawable-xhdpi.drawable-xxhdpi等,同一张图片放到上面不同的文件夹中是有区别的,比如一张100 * 100像素大小的图片,分别

android中图片的三级缓存cache策略(内存/文件/网络)

实现图片缓存也不难,需要有相应的cache策略.这里我采用 内存-文件-网络 三层cache机制,其中内存缓存包括强引用缓存和软引用缓存(SoftReference),其实网络不算cache,这里姑且也把它划到缓存的层次结构中 1.简介 现在android应用中不可避免的要使用图片,有些图片是可以变化的,需要每次启动时从网络拉取,这种场景在有广告位的应用以及纯图片应用(比如百度美拍)中比较多. 现在有一个问题:假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量.在当前的状况下,对于非wi

Android中使用&quot;running services&quot;查看service进程内存

从Android 2.0开始,在Settings中加入了一个新的activity("Running Services" activity),它用于显示当前运行的每个Services进程的内存使用情况及整个手机的内存大致使用情况.可以通过Setting->Applications->Running services进入该activity. Running Services界面如下: 图1: Running Services主要是当前正在运行的Services进程的一个列表.

网站运维工具使用iis日志分析工具分析iis日志(iis日志的配置)

我们只能通过各种系统日志来分析网站的运行状况,对于部署在IIS上的网站来说,IIS日志提供了最有价值的信息,我们可以通过它来分析网站的响应情况,来判断网站是否有性能问题,或者存在哪些需要改进的地方 对于一个需要长期维护的网站来说,如何让网站长久稳定运行是件很有意义的事情.有些在开发阶段没有暴露的问题很有可能就在运维阶段出现了,这也是很正常的.还有些时候,我们希望不断地优化网站,让网站更快速的响应用户请求,这些事情都发生在开发之后的运维阶段. 与开发阶段不同的,运维阶段不可能让你去调试程序,发现各