-
内存分析工具MAT
2018-01-09 18:16:19Android内存分析工具,和AS的.hprof文件配合使用分析应用APP的内存。 -
内存分析工具mat使用.doc
2019-12-27 02:46:57内存分析工具MAT的使用 一MAT插件安装 MAT(Memory Analyzer Tool) 是基于heap dumps来进行分析的它的分析速度比jhat快分析结果是图形界面显示比java内置jhat的可读性更高,通过Eclipse市场安装 方法/步骤1 打开... -
内存分析工具 MAT 的使用
2014-09-18 17:39:50内存分析工具 MAT1 内存泄漏的排查方法
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文件
1.3 Histogram 查询
用的最多的功能是 Histogram,点击 Actions下的 Histogram项将得到 Histogram结果:
它按类名将所有的实例对象列出来,可以点击表头进行排序,在表的第一行可以输入正则表达式来匹配结果 :
在某一项上右键打开菜单选择 list objects ->with incoming refs 将列出该类的实例:
它展示了对象间的引用关系,比如展开后的第一个子项表示这个 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
-
jvm内存分析工具mat安装包
2020-05-11 15:05:07JVM内存dump分析工具MAT独立安装包,分析内存溢出利器,可以准确定位内存异常原因,解决问题,MemoryAnalyzer-1.10.0.20200225.zip -
jvm内存分析工具mat
2019-09-20 23:53:57mat用于分析JVM的内存dump信息,是在JVM内存异常时进行内存分析的好工具 -
Android内存优化(五)详解内存分析工具MAT
2017-08-11 00:30:45在这个系列的前四篇文章中,我分别介绍了DVM、ART、内存泄漏和内存检测工具的相关知识点,这一篇我们通过一个小例子,来学习如何使用内存分析工具MAT。相关文章
Android性能优化系列
Java虚拟机系列前言
在这个系列的前四篇文章中,我分别介绍了DVM、ART、内存泄漏和内存检测工具的相关知识点,这一篇我们通过一个小例子,来学习如何使用内存分析工具MAT。
1.概述
在进行内存分析时,我们可以使用Memory Monitor和Heap Dump来观察内存的使用情况、使用Allocation Tracker来跟踪内存分配的情况,也可以通过这些工具来找到疑似发生内存泄漏的位置。但是如果想要深入的进行分析并确定内存泄漏,就要分析
疑似发生内存泄漏时所生成堆存储文件。堆存储文件可以使用DDMS或者Memory Monitor来生成,输出的文件格式为hpof,而MAT就是来分析堆存储文件的。
MAT,全称为Memory Analysis Tool,是对内存进行详细分析的工具,它是Eclipse的插件,如果用Android Studio进行开发则需要单独下载它,下载地址为:http://eclipse.org/mat/,这篇文章MAT的版本为1.6.1。2.生成hpof文件
2.1 准备内存泄漏代码
我们需要准备一段发生内存泄漏代码,如下所示。
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); LeakThread leakThread = new LeakThread(); leakThread.start(); } class LeakThread extends Thread { @Override public void run() { try { Thread.sleep(60 * 60 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
上面的代码是很典型的内存泄漏的例子,原因就是非静态内部类LeakThread持有外部类MainActivity的引用,LeakThread中做了耗时操作,导致MainActivity无法被释放,关于内存泄漏可以查看Android内存优化(三)避免可控的内存泄漏这篇文章。
2.2 DDMS生成hpof文件
生成hpof文件主要分为以下几个步骤:
1. 在Android Studio中打开DDMS,运行程序。
2. 在Devices中选择要分析的应用程序进程,点击Update Heap按钮(装有一半绿色液体的圆柱体)开始进行追踪。
3. 进行可能发生内存问题的操作(本文的例子就是不断的切换横竖屏)。
4. 点击Dump HPROP File按钮结束追踪,生成并保存hprof文件,如下图所示。DDMS生成的hprof文件并不是标准的,还需要将它转换为标准的hprof文件,这样才会被MAT识别从而进行分析,可以使用SDK自带的hprof-conv进行转换,它的路径在sdk/platform-tools中,进入到该路径执行以下语句即可:
hprof-conv D:\before.hprof D:\after.hprof
其中 D:\before.hprof 是要转换的hprof文件路径,D:\after.hprof 则是转换后hprof文件的保存路径。
2.3 Memory Monitor生成hpof文件
除了用DDMS来生成hpof文件,还可以用AS的Memory Monitor来生成hpof文件。
生成hpof文件主要分为一下几个步骤:
1. 在Android Monitor中选择要分析的应用程序进程。
2. 进行可能发生内存问题的操作(本文的例子就是不断的切换横竖屏)。
3. 点击Dump Java Heap按钮,生成hprof文件,如下图所示。Memory Monitor生成的hpof文件也不是标准的,AS提供了便捷的转换方式:Memory Monitor生成的hpof文件都会显示在AS左侧的Captures标签中,在Captures标签中选择要转换的hpof文件,并点击鼠标右键,在弹出的菜单中选择Export to standard.hprof选项,即可导出标准的hpof文件,如下图所示。
3.MAT分析hpof文件
用MAT打开标准的hpof文件,选择Leak Suspects Report选项。这时MAT就会生成报告,这个报告分为两个标签页,一个是Overview,一个是Leak Suspects(内存泄漏猜想),如下图所示。
Leak Suspects中会给出了MAT认为可能出现内存泄漏问题的地方,上图共给出了3个内存泄漏猜想,通过点击每个内存泄漏猜想的Details可以看到更深入的分析清理情况。如果内存泄漏不是特别的明显,通过Leak Suspects是很难发现内存泄漏的位置。打开Overview标签页,首先看到的是一个饼状图,它主要用来显示内存的消耗,饼状图的彩色区域代表被分配的内存,灰色区域的则是空闲内存,点击每个彩色区域可以看到这块区域的详细信息,如下图所示。
再往下看,Actions一栏的下面列出了MAT提供的四种Action,其中分析内存泄漏最常用的就是Histogram和Dominator Tree。我们点击Actions中给出的链接或者在MAT工具栏中就可以打开Dorminator Tree和Histogram,如下图所示。
其中左边第二个选项是Histogram,第三个选项是Dorminator Tree,第四个是OQL,下面分别对它们进行介绍。
3.1 Dominator Tree
Dorminator Tree意味支配树,从名称就可以看出Dorminator Tree更善于去分析对象的引用关系。
图中可以看出Dorminator Tree有三列数据。
- Shallow Heap:对象自身占用的内存大小,不包括它引用的对象。如果是数组类型的对象,它的大小是数组元素的类型和数组长度决定。如果是非数组类型的对象,它的大小由其成员变量的数量和类型决定。
- Retained Heap:一个对象的Retained Set所包含对象所占内存的总大小。换句话说,Retained Heap就是当前对象被GC后,从Heap上总共能释放掉的内存。Retained Set指的是这个对象本身和他持有引用的对象以及这些引用对象的Retained Set所占内存大小的总和,官方的图解如下所示。
从图中可以看出E的Retained Set为E和G。C的Retained Set为C、D、E、F、G、H。
MAT所定义的支配树就是从上图的引用树演化而来。在引用树当中,一条到Y的路径必然会经过X,这就是X支配Y。X直接支配Y则指的是在所有支配Y的对象中,X是Y最近的一个对象。支配树就是反映的这种直接支配关系,在支配树中,父节点直接支配子节点。下图就是官方提供的一个从引用树到支配树的转换示意图。C直接支配D、E,因此C是D、E的父节点,这一点根据上面的阐述很容易得出结论。C直接支配H,这可能会有些疑问,能到达H的主要有两条路径,而这两条路径FD和GE都不是必须要经过的节点,只有C满足了这一点,因此C直接支配H,C就是H的父节点。通过支配树,我们就可以很容易的分析一个对象的Retained Set,比如E被回收,则会释放E、G的内存,而不会释放H的内存,因为F可能还引用着H,只有C被回收,H的内存才会被释放。
这里对支配树进行了讲解,我们可以得出一个结论:通过MAT提供的Dominator Tree,可以很清晰的得到一个对象的直接支配对象,如果直接支配对象中出现了不该有的对象,就说明发生了内存泄漏。
在Dominator Tree的顶部Regex可以输入过滤条件(支持正则表达式),如果是查找Activity内存泄漏,可以在Regex中输入Activity的名称,比如我们这个例子可以输入MainActivity,效果如下图所示。
Dominator Tree中列出了很多MainActivity实例,MainActivity是不该有这么多实例的,基本可以断定发生了内存泄漏,具体内存泄漏的原因,可以查看GC引用链。在MainActivity一项单击鼠标右键,选择Merge Shortest Paths to GC Root,如下图所示。Merge Shortest Paths to GC Root选项主要用来显示距离GC Root最短的路径,根据引用类型会有多种选项,比如with all references就是包含所有的引用,这里我们选择exclude all phantom/weak/soft etc. references,因为这个选项排除了虚引用、弱引用和软引用,这些引用一般是可以被回收的。这时MAT就会给出MainActivity的GC引用链。
引用MainActivity的是LeakThread,this$0的含义就是内部类自动保留的一个指向所在外部类的引用,而这个外部类就是MainActivity,这将会导致MainActivity无法被GC。3.2 Histogram
Histogram与Dominator Tree不同的是,Dominator Tree是在对象实例的角度上进行分析,注重引用关系分析,而Histogram则在类的角度上进行分析,注重量的分析。
Histogram中的内容如下图所示。可以看到Histogram中共用四列数据,关于Shallow Heap和Shallow Heap的含义我们在3.1节已经知道了,剩余的 Class Name代表类名,Objects代表对象实例的个数。
在Histogram的顶部Regex同样可以输入过滤条件,这里同样输入MainActivity,效果如下图所示。
MainActivity和LeakThread实例各为11个,基本上可以断定发生了内存泄漏。具体内存泄漏的原因,同样可以查看GC引用链。在MainActivity一项单击鼠标右键,选择Merge Shortest Paths to GC Root,并在选项中选择exclude all phantom/weak/soft etc. references如下图所示。
得出的结果和3.1节是相同的,引用MainActivity的是LeakThread,这导致了MainActivity无法被GC。3.3 OQL
OQL全称为Object Query Language,类似于SQL语句的查询语言,能够用来查询当前内存中满足指定条件的所有的对象。它的查询语句的基本格式为:
SELECT * FROM [ INSTANCEOF ] <class_name> [ WHERE <filter-expression>]
当我们输入select * from instanceof android.app.Activity并按下F5时(或者按下工具栏的红色叹号),会将当前内存中所有Activity都显示出来,如下图所示。
如果Activty比较多,或者你想查找具体的类,可以直接输入具体类的完整名称:select * from com.example.liuwangshu.leak.MainActivity
通过查看GC引用链也可以找到内存泄漏的原因。关于OQL语句有很多用法,具体可以查看官方文档。
3.4 对比hpof文件
因为我们这个例子很简单,可以通过上面的方法来找到内存泄漏的原因,但是复杂的情况就需要通过对比hpof文件来进行分析了。使用步骤为:
1. 操作应用,生成第一个hpof文件。
2. 进行一段时间操作,再生成第二个hpof文件。
3. 用MAT打开这两个hpof文件。
4. 将第一个和第二个hpof文件的Dominator Tree或者Histogram添加到Compare Basket中,如下图所示。
5. 在Compare Basket中点击红色叹号按钮生成Compared Tables,Compared Tables如下图所示。在Compared Tables也有顶部Regex,输入MainActivity进行筛选。
可以看到MainActivity在这一过程中增加了6个,MainActivity的实例不应该增加的,这说明发生了内存泄漏,可以通过查看GC引用链来找到内存泄漏的具体的原因。
除了上面的对比方法,Histogram还可以通过工具栏的对比按钮来进行对比:
生成的结果和Compared Tables类似,我们输入MainActivity进行筛选:
可以看到第二个hpof文件比第一个hpof文件多了6个MainActivity实例。
MAT还有很多功能,这里也只介绍了常用的功能,其他的功能就需要读者在使用过程中去发现并积累。
参考资料
《Android群英传 神兵利器》
《Android应用性能优化最佳实践》
《高性能Android应用开发》
利用MAT进行内存泄露分析
Android最佳性能实践(二)——分析内存的使用情况
Memory Analyzer欢迎关注我的微信公众号,第一时间获得博客更新提醒,以及更多成体系的Android相关原创技术干货。
扫一扫下方二维码或者长按识别二维码,即可关注。 -
内存分析_JVM 内存分析工具 MAT
2021-01-15 08:06:18MAT(Memory Analyzer Tools)是一个快速且功能丰富的 Java 堆分析器,可帮助您查找内存泄漏...1 简介MAT 是一款非常强大的内存分析工具,在 Eclipse 中有相应的插件,同时也有单独的安装包。在进行内存分析时,只要获...MAT(Memory Analyzer Tools)
是一个快速且功能丰富的 Java 堆分析器,可帮助您查找内存泄漏并减少内存消耗。使用 MAT 分析具有数亿个对象的高效堆转储,快速计算对象的保留大小,查看谁阻止垃圾收集器收集对象,运行报告以自动提取泄漏嫌疑者。1 简介
MAT 是一款非常强大的内存分析工具,在 Eclipse 中有相应的插件,同时也有单独的安装包。在进行内存分析时,只要获得了反映当前设备内存映像的
hprof
文件,通过 MAT 打开就可以直观地看到当前的内存信息。2 使用
2.1 准备 MAT
下载独立版本的 MAT,下载地址:https://www.eclipse.org/mat/downloads.php,下载后解压。找到
MemoryAnalyzer.ini
文件,该文件里面有个 Xmx 参数,该参数表示最大内存占用量,默认为 1024m,根据堆转储文件大小修改该参数即可。2.2 准备堆转储文件(Heap Dump)
堆转储文件(Heap Dump)是 Java 进程在某个时间内的快照(.hprof 格式)。它在触发快照的时候保存了很多信息,如:Java 对象和类信息(通常在写堆转储文件前会触发一次 Full GC)。
堆转储文件信息:
- 所有的对象信息,包括对象实例、成员变量、存储于栈中的基本类型值和存储于堆中的其他对象的引用值。
- 所有的类信息,包括 classloader、类名称、父类、静态变量等。
- GC Root 到所有的这些对象的引用路径。
- 线程信息,包括线程的调用栈及此线程的线程局部变量(TLS)。
多种方式获取堆转储文件:
- 通过 jmap 命令可以在 cmd 里执行:
jmap -dump:format=b,file=
。 - 如果想在发生内存溢出的时候自动 dump,需要添加下面 JVM 参数:
-XX:+HeapDumpOnOutOfMemoryError
。 - 使用 Ctrl+Break 组合键主动获取获取,需要添加下面 JVM 参数:
-XX:+HeapDumpOnCtrlBreak
。 - 使用 HPROF Agent 可以在程序执行结束时或受到 SIGOUT 信号时生成 Dump 文件,配置在虚拟机的参数如下:
-agentlib:hprof=heap=dump,format=b
。 - 使用 JConsole 获取。
- 使用 Memory Analyzer Tools 的
File -> Acquire Heap Dump
功能获取。
2.3 分析堆转储文件
打开 MAT 之后,加载 dump 文件,差不多就下面这样的界面:
常用的两个功能:
Histogram、 Leak Suspects
。2.3.1 Histogram
Histogram 可以列出内存中的对象,对象的个数及其内存大小,可以用来定位哪些对象在 Full GC 之后还活着,哪些对象占大部分内存。
- Class Name:类名称,Java 类名。
- Objects:类的对象的数量,这个对象被创建了多少个。
- Shallow Heap:对象本身占用内存的大小,不包含其引用的对象内存,实际分析中作用不大。常规对象(非数组)的 Shallow Size 由其成员变量的数量和类型决定。数组的 Shallow Size 由数组元素的类型(对象类型、基本类型)和数组长度决定。对象成员都是些引用,真正的内存都在堆上,看起来是一堆原生的 byte[], char[], int[],对象本身的内存都很小。
- Retained Heap:计算方式是将 Retained Set(当该对象被回收时那些将被 GC 回收的对象集合)中的所有对象大小叠加。或者说,因为 X 被释放,导致其它所有被释放对象(包括被递归释放的)所占的 heap 大小。Retained Heap 可以更精确的反映一个对象实际占用的大小。
Retained Heap 例子:一个 ArrayList 对象持有 100 个对象,每一个占用 16 bytes,如果这个 list 对象被回收,那么其中 100 个对象也可以被回收,可以回收 16*100 + X 的内存,X 代表 ArrayList 的 shallow 大小。
在上述列表中选择一个 Class,右键选择
List objects > with incoming references
,在新页面会显示通过这个 class 创建的对象信息。继续选择一个对象,右键选择
Path to GC Roots > ****
,通常在排查**内存泄漏(一般是因为存在无效的引用)**的时候,我们会选择exclude all phantom/weak/soft etc.references
,意思是查看排除虚引用/弱引用/软引用等的引用链,因为被虚引用/弱引用/软引用的对象可以直接被 GC 给回收,我们要看的就是某个对象否还存在 Strong 引用链(在导出 Heap Dump 之前要手动触发 GC 来保证),如果有,则说明存在内存泄漏,然后再去排查具体引用。这时会拿到 GC Roots 到该对象的路径,通过对象之间的引用,可以清楚的看出这个对象没有被回收的原因,然后再去定位问题。如果上面对象此时本来应该是被 GC 掉的,简单的办法就是将其中的某处置为 null 或者 remove 掉,使其到 GC Root 无路径可达,处于不可触及状态,垃圾回收器就可以回收了。反之,一个存在 GC Root 的对象是不会被垃圾回收器回收掉的。
2.3.2 Leak Suspects
Leak Suspects 可以自动分析并提示可能存在的内存泄漏,可以直接定位到 Class 及对应的行数。
比如:这里问题一的描述,列出了一些比较大的实例。点击
Details
可以看到细节信息,另外还可点击See stacktrace
查看具体的线程栈信息(可直接定位到具体某个类中的方法)。在 Details 详情页面
Shortest Paths To the Accumulation Point
表示 GC root 到内存消耗聚集点的最短路径,如果某个内存消耗聚集点有路径到达 GC root,则该内存消耗聚集点不会被当做垃圾被回收。实战:在某项目中,其中几个 Tomcat 响应特别慢,打开
Java VisualVM
观察Tomcat(pid xxx)-Visual GC
发现Spaces-Old
升高,Graphs-GC Time
比较频繁且持续时间长、有尖峰(重启后过段时间又出现了),最后通过Leak Suspects
中的See stacktrace
定位到某个查询接口,仔细排查代码后发现有个 BUG:在特定查询条件下会一次性查询几万的数据出来(因为脏数据),处理过后恢复正常。2.3.3 内存快照对比
为了更有效率的找出内存泄露的对象,一般会获取两个堆转储文件(先 dump 一个,隔段时间再 dump 一个),通过对比后的结果可以很方便定位。
-
Android内存优化:详解内存分析工具MAT
2018-06-07 15:48:24前言在这个系列的前四篇文章中,我分别介绍了DVM、ART、内存泄漏和内存检测工具的相关知识点,这一篇我们通过一个小例子,来学习如何使用内存分析工具MAT。1.概述在进行内存分析时,我们可以使用Memory Monitor和...前言
在这个系列的前四篇文章中,我分别介绍了DVM、ART、内存泄漏和内存检测工具的相关知识点,这一篇我们通过一个小例子,来学习如何使用内存分析工具MAT。
1.概述
在进行内存分析时,我们可以使用Memory Monitor和Heap Dump来观察内存的使用情况、使用Allocation Tracker来跟踪内存分配的情况,也可以通过这些工具来找到疑似发生内存泄漏的位置。但是如果想要深入的进行分析并确定内存泄漏,就要分析
疑似发生内存泄漏时所生成堆存储文件。堆存储文件可以使用DDMS或者Memory Monitor来生成,输出的文件格式为hpof,而MAT就是来分析堆存储文件的。
MAT,全称为Memory Analysis Tool,是对内存进行详细分析的工具,它是Eclipse的插件,如果用Android Studio进行开发则需要单独下载它,下载地址为:http://eclipse.org/mat/,这篇文章MAT的版本为1.6.1。2.生成hpof文件
2.1 准备内存泄漏代码
我们需要准备一段发生内存泄漏代码,如下所示。
public class MainActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); LeakThread leakThread = new LeakThread(); leakThread.start(); } class LeakThread extends Thread { public void run() { try { Thread.sleep(60 * 60 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
上面的代码是很典型的内存泄漏的例子,原因就是非静态内部类LeakThread持有外部类MainActivity的引用,LeakThread中做了耗时操作,导致MainActivity无法被释放,关于内存泄漏可以查看Android内存优化(三)避免可控的内存泄漏这篇文章。
2.2 DDMS生成hpof文件
生成hpof文件主要分为以下几个步骤:
- 在Android Studio中打开DDMS,运行程序。
- 在Devices中选择要分析的应用程序进程,点击Update Heap按钮(装有一半绿色液体的圆柱体)开始进行追踪。
- 进行可能发生内存问题的操作(本文的例子就是不断的切换横竖屏)。
- 点击Dump HPROP File按钮结束追踪,生成并保存hprof文件,如下图所示。
DDMS生成的hprof文件并不是标准的,还需要将它转换为标准的hprof文件,这样才会被MAT识别从而进行分析,可以使用SDK自带的hprof-conv进行转换,它的路径在sdk/platform-tools中,进入到该路径执行以下语句即可:
hprof-conv D:\before.hprof D:\after.hprof
其中 D:\before.hprof 是要转换的hprof文件路径,D:\after.hprof 则是转换后hprof文件的保存路径。
2.3 Memory Monitor生成hpof文件
除了用DDMS来生成hpof文件,还可以用AS的Memory Monitor来生成hpof文件。
生成hpof文件主要分为一下几个步骤:- 在Android Monitor中选择要分析的应用程序进程。
- 进行可能发生内存问题的操作(本文的例子就是不断的切换横竖屏)。
- 点击Dump Java Heap按钮,生成hprof文件,如下图所示。
Memory Monitor生成的hpof文件也不是标准的,AS提供了便捷的转换方式:Memory Monitor生成的hpof文件都会显示在AS左侧的Captures标签中,在Captures标签中选择要转换的hpof文件,并点击鼠标右键,在弹出的菜单中选择Export to standard.hprof选项,即可导出标准的hpof文件,如下图所示。
QQ截图20170810232344.png
3.MAT分析hpof文件
用MAT打开标准的hpof文件,选择Leak Suspects Report选项。这时MAT就会生成报告,这个报告分为两个标签页,一个是Overview,一个是Leak Suspects(内存泄漏猜想),如下图所示。
Leak Suspects中会给出了MAT认为可能出现内存泄漏问题的地方,上图共给出了3个内存泄漏猜想,通过点击每个内存泄漏猜想的Details可以看到更深入的分析清理情况。如果内存泄漏不是特别的明显,通过Leak Suspects是很难发现内存泄漏的位置。打开Overview标签页,首先看到的是一个饼状图,它主要用来显示内存的消耗,饼状图的彩色区域代表被分配的内存,灰色区域的则是空闲内存,点击每个彩色区域可以看到这块区域的详细信息,如下图所示。
再往下看,Actions一栏的下面列出了MAT提供的四种Action,其中分析内存泄漏最常用的就是Histogram和Dominator Tree。我们点击Actions中给出的链接或者在MAT工具栏中就可以打开Dorminator Tree和Histogram,如下图所示。
其中左边第二个选项是Histogram,第三个选项是Dorminator Tree,第四个是OQL,下面分别对它们进行介绍。
3.1 Dominator Tree
Dorminator Tree意味支配树,从名称就可以看出Dorminator Tree更善于去分析对象的引用关系。
图中可以看出Dorminator Tree有三列数据。
- Shallow Heap:对象自身占用的内存大小,不包括它引用的对象。如果是数组类型的对象,它的大小是数组元素的类型和数组长度决定。如果是非数组类型的对象,它的大小由其成员变量的数量和类型决定。
- Retained Heap:一个对象的Retained Set所包含对象所占内存的总大小。换句话说,Retained Heap就是当前对象被GC后,从Heap上总共能释放掉的内存。
Retained Set指的是这个对象本身和他持有引用的对象以及这些引用对象的Retained Set所占内存大小的总和,官方的图解如下所示。
从图中可以看出E的Retained Set为E和G。C的Retained Set为C、D、E、F、G、H。
MAT所定义的支配树就是从上图的引用树演化而来。在引用树当中,一条到Y的路径必然会经过X,这就是X支配Y。X直接支配Y则指的是在所有支配Y的对象中,X是Y最近的一个对象。支配树就是反映的这种直接支配关系,在支配树中,父节点直接支配子节点。下图就是官方提供的一个从引用树到支配树的转换示意图。C直接支配D、E,因此C是D、E的父节点,这一点根据上面的阐述很容易得出结论。C直接支配H,这可能会有些疑问,能到达H的主要有两条路径,而这两条路径FD和GE都不是必须要经过的节点,只有C满足了这一点,因此C直接支配H,C就是H的父节点。通过支配树,我们就可以很容易的分析一个对象的Retained Set,比如E被回收,则会释放E、G的内存,而不会释放H的内存,因为F可能还引用着H,只有C被回收,H的内存才会被释放。
这里对支配树进行了讲解,我们可以得出一个结论:通过MAT提供的Dominator Tree,可以很清晰的得到一个对象的直接支配对象,如果直接支配对象中出现了不该有的对象,就说明发生了内存泄漏。
在Dominator Tree的顶部Regex可以输入过滤条件(支持正则表达式),如果是查找Activity内存泄漏,可以在Regex中输入Activity的名称,比如我们这个例子可以输入MainActivity,效果如下图所示。
Dominator Tree中列出了很多MainActivity实例,MainActivity是不该有这么多实例的,基本可以断定发生了内存泄漏,具体内存泄漏的原因,可以查看GC引用链。在MainActivity一项单击鼠标右键,选择Path To GC Roots,如下图所示。Path To GC Roots选项用来表示从对象到GC Roots的路径,根据引用类型会有多种选项,比如with all references就是包含所有的引用,这里我们选择exclude all phantom/weak/soft etc. references,因为这个选项排除了虚引用、弱引用和软引用,这些引用一般是可以被回收的。这时MAT就会给出MainActivity的GC引用链。
引用MainActivity的是LeakThread,this$0的含义就是内部类自动保留的一个指向所在外部类的引用,而这个外部类就是MainActivity,这将会导致MainActivity无法被GC。3.2 Histogram
Histogram与Dominator Tree不同的是,Dominator Tree是在对象实例的角度上进行分析,注重引用关系分析,而Histogram则在类的角度上进行分析,注重量的分析。
Histogram中的内容如下图所示。可以看到Histogram中共用四列数据,关于Shallow Heap和Shallow Heap的含义我们在3.1节已经知道了,剩余的 Class Name代表类名,Objects代表对象实例的个数。
在Histogram的顶部Regex同样可以输入过滤条件,这里同样输入MainActivity,效果如下图所示。
MainActivity和LeakThread实例各为11个,基本上可以断定发生了内存泄漏。具体内存泄漏的原因,同样可以查看GC引用链。在MainActivity一项单击鼠标右键,选择Merge Shortest Paths to GC roots ,并在选项中选择exclude all phantom/weak/soft etc. references如下图所示。
Histogram是在类的角度进行分析,而Path To GC Roots是用来分析单个对象的,因此在Histogram无法使用Path To GC Roots查询,可以使用Merge Shortest Paths to GC roots查询,它表示从GC roots到一个或一组对象的公共路径。
得出的结果和3.1节是相同的,引用MainActivity的是LeakThread,这导致了MainActivity无法被GC。3.3 OQL
OQL全称为Object Query Language,类似于SQL语句的查询语言,能够用来查询当前内存中满足指定条件的所有的对象。它的查询语句的基本格式为:
SELECT * FROM [ INSTANCEOF ] <class_name> [ WHERE <filter-expression>]
当我们输入select * from instanceof android.app.Activity并按下F5时(或者按下工具栏的红色叹号),会将当前内存中所有Activity都显示出来,如下图所示。
如果Activty比较多,或者你想查找具体的类,可以直接输入具体类的完整名称:select * from com.example.liuwangshu.leak.MainActivity
通过查看GC引用链也可以找到内存泄漏的原因。关于OQL语句有很多用法,具体可以查看官方文档。
3.4 对比hpof文件
因为我们这个例子很简单,可以通过上面的方法来找到内存泄漏的原因,但是复杂的情况就需要通过对比hpof文件来进行分析了。使用步骤为:
- 操作应用,生成第一个hpof文件。
- 进行一段时间操作,再生成第二个hpof文件。
- 用MAT打开这两个hpof文件。
- 将第一个和第二个hpof文件的Dominator Tree或者Histogram添加到Compare Basket中,如下图所示。
- 在Compare Basket中点击红色叹号按钮生成Compared Tables,Compared Tables如下图所示。
在Compared Tables也有顶部Regex,输入MainActivity进行筛选。
可以看到MainActivity在这一过程中增加了6个,MainActivity的实例不应该增加的,这说明发生了内存泄漏,可以通过查看GC引用链来找到内存泄漏的具体的原因。
除了上面的对比方法,Histogram还可以通过工具栏的对比按钮来进行对比:
生成的结果和Compared Tables类似,我们输入MainActivity进行筛选:
可以看到第二个hpof文件比第一个hpof文件多了6个MainActivity实例。
MAT还有很多功能,这里也只介绍了常用的功能,其他的功能就需要读者在使用过程中去发现并积累。
参考资料
分享到 评论 上一篇
《Android群英传 神兵利器》
《Android应用性能优化最佳实践》
《高性能Android应用开发》
利用MAT进行内存泄露分析
Android最佳性能实践(二)——分析内存的使用情况
Memory Analyzer《Android进阶之光》勘误下一篇React Native组件(四)TextInput组件解析 -
Mac OS java内存分析工具MAT
2018-12-18 17:06:03Mac OS java内存分析工具,Eclipse MAT(Memory analyse tool) -
android内存分析工具MAT的使用
2017-04-14 15:19:24android内存分析工具MAT的使用 当遇到OutOfMemory问题的时候,怎么样通过MAT来定位和分析问题呢?先看个例子: public class MemoryLeakActivity extends AppCompatActivity{ @Override protected void ... -
内存分析工具MAT 的使用
2016-02-20 13:44:16[Android Memory] 内存分析工具 MAT 的使用 转载自: http://blog.csdn.net/aaa2832/article/details/19419679 1 内存泄漏的排查方法 Dalvik Debug Monitor Server (DDMS) 是 ADT插件的一部分... -
iview select 内存泄漏_JVM 内存分析工具 MAT 的深度讲解与实践——入门篇
2020-12-25 20:40:15本系列共计3篇:《JVM 内存分析工具 MAT 的深度讲解与实践——入门篇》介绍 MAT 产品功能、基础概念、与其他工具对比、Quick Start 指南。《JVM 内存分析工具 MAT 的深度讲解与实践——进阶篇》展开并详细介绍 MAT ... -
JVM 内存分析工具 MAT 的深度讲解与实践——入门篇
2020-12-23 11:15:24《JVM 内存分析工具 MAT 的深度讲解与实践——入门篇》介绍 MAT 产品功能、基础概念、与其他工具对比、Quick Start 指南。 《JVM 内存分析工具 MAT 的深度讲解与实践——进阶篇》展开并详细介绍 . -
eclipse内存分析工具MAT使用
2014-12-03 11:32:25eclipse内存分析工具MAT使用 MAT(Memory Analyzer Tool) 是基于heap dumps来进行分析的,所以首先必须通过一定的手段得到JAVA堆的DUMP文件。JDK自带的。JConsole 或者 JMAP都是不错的工具。 准备 (·... -
Android内存优化(三)详解内存分析工具MAT
2018-07-18 09:54:00在这个系列的前四篇文章中,我分别介绍了DVM、ART、内存泄漏和内存检测工具的相关知识点,这一篇我们通过一个小例子,来学习如何使用内存分析工具MAT。 1.概述 在进行内存分析时,我们可以使用Memory Monitor和... -
JVM调优之内存分析工具MAT的使用
2019-03-28 11:40:11在spark streaming程序持续运行中,经过一段时间之后,executor频繁发生GC time,导致每个批次处理时间变长,推测程序存在内存泄漏,因此引入MAT内存分析工具 MAT的安装 由于我们已经习惯了IDEA开发,为了MAT下载个... -
内存分析工具MAT介绍
2019-08-12 10:27:24MAT(Memory Analyzer Tool)是一个基于Eclipse的内存分析工具,是一个快速、功能丰富的java heap分析工具,它可以帮助我们查找内存泄漏和减少内存消耗。 官网地址:https://www.eclipse.org/mat/ 这里我们下载... -
hprof文件分析工具_JVM 内存分析工具 MAT
2020-12-01 04:14:18MAT(Memory Analyzer Tools)是一个快速且功能丰富的 Java 堆分析器,可帮助您查找内存泄漏...1 简介MAT 是一款非常强大的内存分析工具,在 Eclipse 中有相应的插件,同时也有单独的安装包。在进行内存分析时,只要获... -
JVM 内存分析工具 MAT 的深度讲解与实践——进阶篇
2021-01-04 21:34:28本文详细讲解 MAT 众多内存分析工具功能,这些功能组合使用异常强大,熟练使用几乎可以解决所有的堆内存离线分析的问题。我们将功能划分为4类:内存分布详情、对象间依赖、对象状态详情、按条件检索。每大类有多个... -
内存分析工具MAT分析内存溢出问题
2019-07-30 17:22:32MAT下载安装: 1.在eclipse中安装插件 ...MAT分析的是hprof文件,hprof文件记录了JVM内存溢出时的堆信息,通过分析该文件我们可以分析溢出原因。 JVM参数配置: -Xms10M -Xmx10M -XX:+HeapDumpOnOutOfMemoryEr... -
eclipse内存分析工具MAT浅谈
2013-07-17 12:44:00eclipse内存分析工具MAT浅谈 博客分类: 开发工具 javaeclipsejvmmemory analyzer MAT(Memory Analyzer Tool) 是基于heap dumps来进行分析的,所以首先必须通过一定的手段得到JAVA堆的DUMP文件。...