使用Eclipse Memory Analyzer Tool(MAT)分析线上故障(一) - 视图&功能篇
Eclipse Memory Analyzer Tool(MAT)相关文章目录:
使用Eclipse Memory Analyzer Tool(MAT)分析线上故障(一) - 视图&功能篇
使用Eclipse Memory Analyzer Tool(MAT)分析线上故障(二) - 概念篇
Eclipse Memory Analyzer Tool(MAT)是一个强大的基于Eclipse的内存分析工具,可以帮助我们找到内存泄露,减少内存消耗。
工作中经常会遇到一些内存溢出、内存泄露等问题,同时还可能导致CPU使用率也很高,因为在频繁的进行GC垃圾回收,这时候就需要分析导致问题的原因,MAT是一个比较好用的工具,但刚开始使用时对于其提供的一些功能还是不太了解,故在此总结一下个人觉得比较有用的一些MAT相关概念,其它功能暂时还未用到或者还没有理解使用方法,后续再补充。
以下是本文的目录大纲:
视图 & 功能
7、Paths to GC Roots(从对象到GC Roots的路径) & Merge Shortest Paths to GC roots(从GC Roots到对象的共同路径)
8、Leak Suspects Report(内存泄露报告)
若有不正之处请多多谅解,欢迎批评指正、互相讨论。
请尊重作者劳动成果,转载请标明原文链接:
http://www.cnblogs.com/trust-freedom/p/6744948.html
视图 & 功能
1、Overview
通过 File > Open Heap Dump... 打开dump文件,最先展示就是Overview概述界面,可以对Heap Dump有一个大致的了解,并提供了一些视图、报告的入口,这些视图、报告都对分析Heap Dump很有帮助,后续会介绍。
鼠标移动到饼图某个区域上方,在左侧会看到对象的详细信息,如左上方的 Inspector 展示了如:对象hashcode、类名、包名、Class类对象、父类、类加载器、shallow size、retained size、GC root类型。左下方展示了对象的一些属性信息、类层级信息。
2、Histogram视图
以下方式可以打开Histogram柱状图:
(1)点击Overview页面Actions区域内的“Histogram视图”链接
(2)点击工具栏的“histogram按钮”
Histogram视图:
该视图以Class类的维度展示每个Class类的实例存在的个数、 占用的 [Shallow内存] 和 [Retained内存] 大小,可以分别排序显示。
从Histogram视图可以看出,哪个Class类的对象实例数量比较多,以及占用的内存比较大,Shallow Heap与Retained Heap的区别会在后面的概念介绍中说明。
不过,多数情况下,在Histogram视图看到实例对象数量比较多的类都是一些基础类型,如char[](因为其构成了String)、String、byte[],所以仅从这些是无法判断出具体导致内存泄露的类或者方法的,可以使用 List objects 或 Merge Shortest Paths to GC roots 等功能继续钻取数据。如果Histogram视图展示的数量多的实例对象不是基础类型,是有嫌疑的某个类,如项目代码中的bean类型,那么就要重点关注了。
3、Dominator Tree(支配树)视图
以下方式可以打开Dominator Tree视图:
(1)点击Overview页面Actions区域内的“Dominator Tree视图”链接
(2)点击工具栏的“Dominator Tree按钮” ,为整个堆打开一个支配树视图
Dominator Tree(支配树)视图:
该视图以实例对象的维度展示当前堆内存中Retained Heap占用最大的对象,以及依赖这些对象存活的对象的树状结构
视图中展示了实例对象名、Shallow Heap大小、Retained Heap大小、以及当前对象的Retained Heap在整个堆中的占比
点开Dominator Tree实例对象左侧的“+”,会展示出下一层(next level),当所有引用了当前实例对象的引用都被清除后,下一层列出的objects就会被垃圾回收
这也阐明了“支配”的含义:父节点的回收会导致子节点也被回收,即因为父节点的存在使得子节点存活
Dominator Tree支配树可以很方便的找出占用Retained Heap内存最多的几个对象,并表示出某些objects的是因为哪些objects的原因而存活,在之后的 Dominator Tree概念 部分会对支配树做更详细的说明和举例
4、Group分组功能
使用Group分组功能的方法是,在 Histogram视图 和 Domiantor Tree视图时,点击工具栏的 Group result by...
可以选择以另一种分组方式显示(默认是No Grouping(objects),即以对象维度分组)
例如在Histogram视图 或 Dominator Tree视图,选择Group by package,可以更好地查看具体是哪个包里的类占用内存大,也很容易定位到自己的应用程序
5、Thread Overview
Thread视图的入口,在工具栏上:
Thread Overview:
在Thread Overview视图可以看到:线程对象/线程栈信息、线程名、Shallow Heap、Retained Heap、类加载器、是否Daemon线程等信息
在分析内存Dump的MAT中还可以看到线程栈信息,这本身就是一个强大的功能,类似于jstack命令的效果
而且还能结合内存Dump分析,看到线程栈帧中的本地变量,在左下方的对象属性区域还能看到本地变量的属性,真的很方便
public class TestThreadOverview {
private String str1 = "str1";
private String str2 = "str2"; public static void main(String[] args) {
TestThreadOverview test = new TestThreadOverview(); String local_str = "local_str"; LockSupport.park();
}
}
在上面代码的Heap Dump分析中,可以看到线程调用栈的信息,以及main线程的 本地变量TestThreadOverview 和 字符串local_str 的信息
上图中第一个框起来的部分是 new TestThreadOverview()对象(代码第6行),TestThreadOverview对象有两个属性str1、str2
第二个框起来的部分是main方法中的字符串变量local_str(代码第8行)
结合左侧的对象属性区域,可以更方便的看清线程中对象的具体情况
6、List objects
在 Histogram 或 Dominator Tree视图,想要看某个条目(对象/类)的引用关系图,可以使用 List objects 功能
(1)选择一个条目后,点击工具栏的 Query Browser > List objects,选择 with outgoing references 或 with incoming references
(2)直接在某个条目上点击右键,也可以选择到List object
List objects --> with outgoing references :查看当前对象持有的外部对象引用(在对象关系图中为从当前对象指向外的箭头)
List objects --> with incoming references :查看当前对象被哪些外部对象所引用(在对象关系图中为指向当前对象的箭头)
例如上面Thread Overview的例子代码中,查看main方法中第6行中的
TestThreadOverview test = new TestThreadOverview();
outgoing references查询结果为:
可以看到TestThreadOverview对象存在3个引用,第一个是TestThreadOverview的Class类对象,因为所有Java类都继承自java.lang.Object,所以都有class对象的引用,后两个是成员变量str1、str2
即列出了当前main方法中的局部变量TestThreadOverview所持有的所有外部对象引用
incoming references查询结果为:
可以看到TestThreadOverview是main线程的一个本地局部变量,main线程本身还是一个GC root,而main线程在某个ThreadGroup中
7、Paths to GC Roots(从对象到GC Roots的路径) & Merge Shortest Paths to GC roots(从GC Roots到对象的共同路径)
Paths to GC Roots :从当前对象到GC roots的路径,这个路径解释了为什么当前对象还能存活,对分析内存泄露很有帮助,这个查询只能针对单个对象使用
Merge Shortest Paths to GC roots :从GC roots到一个或一组对象的公共路径
Path to GC roots 和 Merge shortest Paths to GC roots 这两个查询都有很多选项,如:
意思是在查询到GC root的路径时,是包含所有引用,还是排除一些类型的引用(如软引用、弱引用、虚引用),从GC角度说,一个对象无法被GC,一定是因为有强引用存在,其它引用类型在GC需要的情况下都是可以被GC掉的,所以可以使用 exclude all phantom/weak/soft etc. references 只查看GC路径上的强引用
Path to GC roots 和 Merge shortest Paths to GC roots 的入口和 List objects一样,可以从工具栏的 Query Browser 进入,或者在条目上直接点击右键进入
需要注意的是,Paths to GC roots是针对单个对象的,故在Histogram视图无法使用,因为Histogram视图是针对类的,只能使用Merge shortest Paths to GC roots查询
8、Leak Suspects Report(内存泄露报告)
使用MAT打开一个Dump文件时,会弹出向导窗口,保持默认选项,点Finish,就会导向 Leak Suspects内存泄露报告页面
如果打开Dump时跳过了的话,也可以从其它入口进入,如
(1)工具栏上的 Run Expect System Test > Leak Suspects
(2)Overview页面的Reports部分
Leak Suspects 是MAT帮我们分析的可能有内存泄露嫌疑的地方,可以体现出哪些对象被保持在内存中,以及为什么它们没有被垃圾回收
MAT提供了一个很贴心的功能,将报告的内容压缩打包到一个zip文件,并放在原始堆转储文件的目录下,一般命名为“xxx_Leak_Suspects.zip”,xxx是dump文件的名字,如果需要和同事一起分析这个内存问题的话,只需要把这个小小的zip包发给他就可以了,不需要把整个堆文件发给他。并且整个报告是一个HTML格式的文件,用浏览器就可以轻松打开
内存泄露的概念: |
下面用一个例子分析如何使用Leak Suspects Report内存泄露报告
public class OOMHeapTest {
public static void main(String[] args){
oom();
} private static void oom(){
Map<String, OOMBean> map = new HashMap<String, OOMBean>();
Object[] array = new Object[1000000];
for(int i=0; i<1000000; i++){
String d = new Date().toString();
OOMBean o = new OOMBean(d, i);
map.put(i+"_oom", o);
array[i] = o;
}
}
}
上面的代码中创建了很多OOMBean,并放入了Map和数组中,由于是强引用,在主线程运行结束前,GC自然不会回收,一直到内存溢出。
在运行前设置一些VM参数:-Xms2m -Xmx2m -XX:+HeapDumpOnOutOfMemoryError
以便程序可以OutOfMemory,并在发生内存溢出时自动生成内存快照
程序运行一会儿后,控制台打印
java_pid10160.hprof 就是内存dump,可以在OOMHeapTest类所在工程的根目录下找到
Leak Suspects:
MAT工具分析了heap dump后在界面上非常直观的展示了一个饼图,该图深色区域被怀疑有内存泄漏,可以发现整个heap才6.8M内存,深色区域就占了92.11%。接下来是一个简短的描述,告诉我们main线程占用了大量内存,并且明确指出system class loader加载的“java.lang.Thread”实例有内存聚集,并建议用关键字“java.lang.Thread”进行检查。在下面还有一个“Details”链接,可以查看明细信息。
Details明细:
Details的最开始是Description描述,和前一个页面对内存泄露嫌疑点的描述一致,下面有一些与怀疑的内存泄露点关联的查询结果展示,是分析报告中认为可能会存在问题,协助我们深入分析问题根源的,具体如下:
(1)Shortest Paths To the Accumulation Point
实际上展开的视图是当前对象“java.lang.Thread @ 0xffc59ab0 main”的 Path to GC roots,即到GC roots的路径,点击标题右侧的按钮可以在另一窗口打开
这个视图的作用是可以分析是由于和哪个GC root相连导致当前Retained Heap占用相当大的对象无法被回收
由于是分析内存泄露的报告,找到导致当前对象无法被回收的GC roots,分析这些GC roots是否合理,是有必要的
但本例中由于main线程本身就是GC root,故只有一条数据
(2)Accumulated Objects in Dominator Tree
这个视图以对象的维度展示了以当前对象“java.lang.Thread @ 0xffc59ab0 main”为根的 Dominator Tree支配树,可以方便的看出受当前对象“支配”的对象中哪个占用Retained Heap比较大
观察Accumulated Objects部分,java.lang.Object[1000000]实例 和 java.util.HashMap 和 的Retained Heap(Size)最大,Retained Heap代表从该类实例沿着reference chain往下所能收集到的其他类实例的Shallow Heap(Size)总和,所以明显类实例都聚集在HashMap和Object数组中了
在Accumulated Objects视图中,Retained heap占用最多的是HashMap和object数组,为啥它们会占用这么大的heap呢?这个时候需要分析HashMap和object数组中存放了一些什么对象?接着往下看 Accumulated Objects by Class in Dominator Tree
(3)Accumulated Objects by Class in Dominator Tree
这个视图实际上是展示了以当前对象“java.lang.Thread @ 0xffc59ab0 main”为根的 Dominator Tree支配树,并以Class类分组
可以看到 OOMBean类 的实例最多,有11786个,程序中确实是在循环创建OOMBean实例,并放入object数据和HashMap中
这样就可以确定Heap占用大时由于OOMBean类的实例创建的太多的原因了
(4)Thread Detail
Detail明细的最后由于当前怀疑泄露点为main Thread线程对象,故展示了线程明细信息,调用栈信息,对分析内存溢出的发生位置很有帮忙
参考资料:
Eclipse Memory Analyzer Tool Help
使用Eclipse Memory Analyzer Tool(MAT)分析线上故障(一) - 视图&功能篇的更多相关文章
- [原创]Eclipse Memory Analyzer tool(MAT)工个使用介绍
[原创]Eclipse Memory Analyzer tool(MAT)工个使用介绍
- 使用Memory Analyzer tool(MAT)分析内存泄漏(一)
转载自:http://www.blogjava.net/rosen/archive/2010/05/21/321575.html 前言 在平时工作过程中,有时会遇到OutOfMemoryError,我 ...
- Eclipse Memory Analyzer(MAT)使用
https://user.qzone.qq.com/731573705/blog/1436389384 Eclipse Memory Analyzer(MAT)使用 一.OutOfMemoryErr ...
- 使用Eclipse Memory Analyzer Tool(MAT)分析故障
Eclipse Memory Analyzer Tool(MAT)是一个强大的基于Eclipse的内存分析工具,可以帮助我们找到内存泄露,减少内存消耗. 工作中经常会遇到一些内存溢出.内存泄露等问题, ...
- 使用Memory Analyzer tool(MAT)分析内存泄漏(二)
转载自:http://www.blogjava.net/rosen/archive/2010/06/13/323522.html 前言的前言 写blog就是好,在大前提下可以想说什么写什么,不像投稿那 ...
- 使用Memory Analyzer tool(MAT)分析内存泄漏
前言的前言 写blog就是好,在大前提下可以想说什么写什么,不像投稿那么字字斟酌.上周末回了趟成都办事,所以本文来迟了.K117从达州经由达成线往成都方向走的时候,发现铁路边有条河,尽管我现在也不知道 ...
- mat(Eclipse Memory Analyzer tool)之二--heap dump分析
文章中的shallow.retained关键字的说明见:GC是如何回收时的判断依据.shallow size.retained size 在本文中,将介绍MAT(Eclipse Memory Anal ...
- Eclipse Memory Analyzer(MAT),内存泄漏插件,安装使用一条龙
网上文档很多,但最初都有问题.整理一份,作为备份.使用过程:开发代码写完后,对可能出现内存溢出的代码,添加配置文件,生成.hprof文件,用memory Analyzer分析排查问题,且泄漏内存大小可 ...
- Memory Analyzer tool(MAT)分析内存泄漏---理解Retained Heap、Shallow Heap、GC Root
Shallow Heap Size 指对象自身所占用的内存大小,不包含其引用的对象所占的内存大小. 1.数组类型 数组元素对象所占内存的大小总和. 2.非数组类型 对象与它所有的成员变量大小的总和.当 ...
随机推荐
- VS2010在网络共享目录使用IntelliSense、ipch、sdf和SQL Compact Server相关问题
Microsoft SQL Compact Server 是专用于 Visual Studio 的单机SQL 数据库.数据库文件名的后缀为SDF. 而VS2010 拒绝在网络共享目录中建立和打开SDF ...
- SEO-搜索引擎高级搜索指令
搜索引擎高级搜索指令 1.双引号 把搜索词放在双引号中,代表完全匹配搜索,也就是说搜索结果返回的页面包含双引号中出现的所有的词,连顺序也必须完全匹配.bd和Google 都支持这个指令.例如搜索: & ...
- 手机端rem如何适配_rem详解及使用方法
什么是rem 在我看来,rem就是1rem单位就等于html节点fontsize的像素值.所以改变html节点的fontsize是最为关键的一步.根据手机宽度改变相对大小就可以实现自适应了,就不用什么 ...
- 基础篇系列,JAVA的并发包 - 锁
JAVA中主要锁 synchronized Reentrantlock ReentrantReadWriteLock 问题引入 为什么需要锁? 为什么JAVA有了synchronize还需要Reent ...
- IIS HTTP 错误 500.19 - Internal Server Error HTTP 错误 401.3 - Unauthorized 解决办法
前言:IIS是一个强大的服务器管理器,当遇到 IIS HTTP 错误 500.19 - Internal Server Error HTTP 错误 401.3 - Unauthorized 的解决办 ...
- JAVA基础知识(2)--关键字final的使用
/***Final关键字的使用*@author lihaiming*Email:912547587@qq.com*关键字Final可以修饰属性,方法,类*修饰属性的时候,final修饰的变量是一个常量 ...
- STL部分的实现
C++的STL很强大,里面实现很多功能 就平时经常会用到的vector之类的,自己实现一下, 有哪块错误的希望大神给予指点 vector类模板 template<typename T>cl ...
- WP8.1小梦词典开发2:百度翻译API使用
原文出自:http://www.bcmeng.com/api2/ 小梦昨天和大家分享了WP8.1金山词霸API使用方法,今天继续分享windows phone 8.1中百度翻译API的使用方法.和昨天 ...
- 强大的版本管理工具 Git
Git 简介 git 是一款免费.开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目.是 linux 创始人 Linus Torvalds 为了帮助管理 linux 内核开发而开发的一个开 ...
- javascript . 04 匿名函数、递归、回调函数、对象、基于对象的javascript、状态和行为、New、This、构造函数/自定义对象、属性绑定、进制转换
匿名函数: 没有名字的函数,函数整体加小括号不报错, 函数调用 : a:直接调用 (function (){函数体}) ( ) ; b:事件绑定 document.onlick = functio ...