Eclipse MAT 内存分析工具

记录下andorid开发中 Eclipse下MATMemory Analysis Tools工具使用过程

参考:http://www.blogjava.net/rosen/archive/2010/06/13/323522.html

http://blog.csdn.net/aaa2832/article/details/19419679


        首先实际情况是 Demo中选择界面,进入FragmentActivity,利用Fragement创建大量(24个)webview,退出fragmentActivity之后,heapsize不断增加,利用ddms工具中查看heapsize,从30M增加到60m不等。


一、利用eclipse DDMS中heap工具查看heap

(1)选择ddms视图


(2)选择虚拟机中应用程序的进程,选择红色标记①处更新heap(updata heap),然后点击红色标记③处即可显示heap情况。其中红色标记②是保存内存快照(.hprof文件)按钮,下文将用到。

几个参数意义:HeapSize:heap大小

                         Allocated:已分配大小

    Free:空闲空间大小

                        上图中下面是每种数据类型的详细信息。 需要注意的是,其中因为本例中存在一些图片,因此1-byte array类型的总大小(TotalSize)比较大。

在实际分析中可以参考这些信息进行初步分析(对我来说实现情况中并不好用,可能还图样。。。。)


(二)eclipse MAT工具安装

百度 eclipse在线安装MAT工具即可。具体的,eclipse ->help->install new software...在对话框中选择add(④),然后输入name(⑤随意,你自己命的名)和location(⑥mat在线安装地址目前是http://download.eclipse.org/mat/1.5/update-site/),然后选择OK。在Work With(7)中选择刚才add的,下面框中就会出现MAT更新的信息(8)。选择后一路next即可。因为需要上外网,所以比较担心网速(google android后遗症),后来发现安装MAT其实挺快的。


安装完后右上角会出现MAT视图按钮。如果木有的话可以选择eclipse->windows->open perspectivew->other 中选择即可出现。

(三)MAT工具的使用

在开发时,一般可以在程序刚运行时获取一次快照,然后运行一段时间后,获取一次内存快照,然后比较分析哪些类可能存在内存泄露以及内存泄露的GC引用路径。注意区分强引用,软引用,弱引用和虚引用。


本例的框架是 mainActivity有一个button,可以开启一个FragmentActivity,在fragmentActivity中一次创建24个webView对象。先打开一次fragmentActivity,在DDMS中点击获取内存快照A,然后back之后再打开一次fragmentActivity,获取内存快照B。点击获取后Eclipse会自动分析,按照默认选项打开即可。


3.1先熟悉下MAT的界面。

(1)默认打开的是内存分析报告,是第一个泄露疑点信息。本例中刚开始获取的内存快照A以及快照B中android.content.res.Resources类和android.graphics.NinePatch类占用较多内存,分别是疑点1(problem suspect 1)和疑点2。但是在快照A和快照B中这两部分变化并不大,因此这里并不是这两个问题(如两个快照都有     )。


快照A




快照B




点击按钮,可以打开泄露疑点的详细信息。details信息分别列出了各个类积累的对象()。点击className,即下图中byte[],有一些选项,其中listObject->with incoming reference查看该类的实例对象,并可以查看那些对象拥有这些对象。listObject->with outgoing reference查看该类实例对象并查看这些对象持有哪些对象的引用。另外Path to GCroot可以查看到GCroot的引用路径。



在该页面最下方有,说明了可能存在的一些线索。最后还有,可以连接到目录。点开目录,发现除了刚才的Leaks页面,还有页面,记录了该内存快照的一些信息,可以都点开打开看一下。


(2)除了default report 页面,还有其他常用的页面。比如打开直方图工具。该工具列出了所有的类以及其对象数量和shallow heap和retained heap。(具体的含义参考http://www.blogjava.net/rosen/archive/2010/05/21/321575.html)。同时在类列表最上方还支持正则表达式。

3.2 利用MAT进行内存快照的对比

首先对比这两个快照。

打开直方图后 ,该直方图将会添加到该快照的浏览历史中。选择标记1中的浏览历史,右击直方图,选择add to compare basket,这样就将该直方图加入对比栏中(跟zol手机电脑对比差不多。。。)。对快照B进行同样的操作。然后点开标记2对比栏,选着两个直方图,右键compare tables进行对比。

对于打开的对比界面,选择中的选择different显示,既可以看到两次快照中类的对象的差别。因为每次打开会创建24个WebView,如果存在内存泄露,对象在内存中未销毁,一次应该增加24个对象。那么因此我选择两次快照中增加24个对象的类。发现大部分是webView内核相关。


对比结果并筛选



3.3  利用MAT进行path to GCRoot 路径分析

我们以com.android.org.chromium.android_webview.AwContentsClientCallbackHelper作为切入点,进行path to GC root。对于这个类类,在两个内存快照的直方图中利用正则表达式都找到它,然后选择listObject->with incomeing reference,列出所有对象。在第一个快照中存在24个对象,在第二个快照中存在48个对象。选择两个快照中都存在的对象,然后分别右键 path to GC root-> exclude all phantom/weak/soft ect. reference,选择通过强引用到GCroot的路径。

快照A



快照B 


我们发现对于该对象(@0x43cc1840),在快照A中存在强引用到GCroot,而在快照B中并不存在通过强引用到GC root的路径。那么为什么它依然存在内存中呢?因为其可能通过软引用弱引用或虚引用存在。



同理,我们分析它的软引用。

右键该对象,选择path to GCroot->exclude all phantom/weak reference即可。我们只分析快照B的结果。


快照B



由上图可以看出从该对象到GCroot的一条路径。最终Path到Native stack上的对象中。


具体为什么存在这一条软引用呢?原来是由于输入法相关的原因(inputMethod)。具体的结果由于对底层不够了解还分析不出来。。。。

注:本文中由于不存在强引用到GC Root,因此不存在内存泄露。对于软引用,当heap区中内存够用时将会一直存在,在内存不够用时会触发对该软引用的GC。因此不断的打开关闭demo FragmentActivity,heap区会一直增加,最后heap区达到最大size时将会触发GC。

本文分析完毕。

本人也是菜鸟一枚,第一次写正儿八经的原创博客,经验不足,如果有错误或表述歧义的地方望指出。。






阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页