Java堆分析器 - Eclipse Memory Analyzer Tool(MAT)

       Java堆(heanp dump)文件是一个纯二进制文件,咱们用肉眼去看肯定是不现实的。所以咱们得借助特定的堆分析器来对dump文件做相应的分析。这里我们选用Eclipse Memory Analyzer(MAT)来作为heap dump文件的分析工具。接下来咱们对MAT工具做一个简单的介绍。方便咱们后续分析Java堆(heap dump)

       Eclipse Memory Analyzer Tool(简称MAT)是一个非常强大的的内存分析工具,可以帮助我们分析堆内存,找到内存泄露的地方,减少内存消耗。MAT除了可以作为Eclipse的插件使用。官方也提供了独立的安装版本,我们用IDEA用的比较多,所以使用独立的安装版本,直接进入下载页面 https://www.eclipse.org/mat/downloads.php ,下载适合自己的版本。为了方便大家我这里提前下载了一份Window 64位的安装包 https://download.csdn.net/download/wuyuxing24/12302636

       在介绍MAT工具之前我们先介绍几个常用术语。在MAT工具中这几个术语经常出现:

  • Shallow Size: 对象自身占用的内存大小。
  • Retained Size: 对象本身的Shallow Size + 该对象直接或间接引用到的对象的Shallow Size。(也就是说Retained Size就是该对象被GC之后所能回收的内存的总和)
  • GC Roots: 是一组必须活跃的引用。GC会收集那些不是GC Roots且没有被GC roots引用的对象。基本思路就是通过一系列名为GC Roots 的对象作为起始点开始向下搜索。如果一个对象到GC Roots没有任何引用链相连时,则说明此对象不可用。换句话说就是能被遍历到的(可到达的)对象就被判定为存活,没有被遍历到的就自然被判定为死亡。

哪些对象可以作为Gc Roots的对象:

  • 虚拟机(栈帧中的本地变量表)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI(即一般说的native方法)中引用的对象
image.png

一 MAT结构介绍

MAT.png

1.1 区域一:Inspector区域

       用于展示指定对象的详细信息(选定一个对象的时候),从上到下依次是:内存地址、加载器名称、包名、对象名称、对象所属类的父类、对象所属类的加载器对象对象的堆内存大小(shallow size)、保留大小(retained size)、gc roots信息。

1.2 区域二:Inspector区域下方的区域

       展示对象的一些属性信息、类层级信息。

1.3 区域三:常用工具栏区域

       常用工具按钮从左到右依次是:概览(Overview)、类直方图(Histogram)、支配树(Dominator Tree)、OQL查询、线程视图、报告相关、详细功能(提供了一些更细致的分析能力)。

1.4 区域四:功能视图区域

       根据选择的功能不同,该区域显示对应功能的详细信息。比如我们想看Overview信息(点击区域三常用工具栏的第一个按钮)该区域就会展示heap dump Overview对应的信息。

二 MAT视图,功能

2.1 Overview视图

MAT-Actions-Overview.png

进入Overview视图

  • 使用MAT打开一个heap dump文件,解析完成后,默认就会进入Overview视图页面。
  • 工具栏中点击Overview按钮(区域三常用工具栏的第一个按钮)展示Overview对应的信息。


    image.png

Overview视图使用

       Overview视图界面包括两个部分:一个是对heap dump文件的一个大致的分析,包括占用内存大小,类个数,对象个数,类加载器个数,及用饼图的方式展示对象retained size信息、另一个是提供了一些常用的入口,包括视图入口(Actions)、常用的分析报告入口(Reports)、MAT使用教程入口(Step By Step)]。

       关于Overview视图区域,我们得关注点应该放在饼图上(根据retained size 对所有对象做排序,使用拼图演示结果)。我们可以方便的看到哪些对象的ratained size比较大(如果某个对象的retained size特别大。我们就要特别小心了,可能有问题了)。当我们鼠标点击每个饼图区域(对象)的时候,会弹出一个菜单,我们还可以查看相应对象的详细信息。这个菜单包含的额内容有:

点击Overview饼图区域弹出的菜单.png
  • List objects:
  • with ontgoing references:查看当前对象持有的外部对象引用。
  • with incoming references:查看当前对象被那些外部对象所引用。
  • Show objects by class
  • with ontgoing references: 查看这个对象类型持有的外部对象引用
  • with ontgoing references: 查看这个对象类型被哪些外部对象引用
  • Path To GC Roots: 从对象到GC Roots的路径。这个路径解释了为什么当前对象还能存活,对分析内存泄露很有帮助。(这个查询只能针对单个对象使用)。这里面可能需要咱们对引用有一定的了解,咱们也做一个简单的介绍。

       强引用(strong reference): 大家平常写代码的引用都是这种类型的引用,它可以防止引用的对象被垃圾回收。软引用(soft reference): 内存溢出之前进行回收,GC时内存不足时回收,如果内存足够就不回收。弱引用(weak reference): 每次GC时回收,无论内存是否足够。虚引用(phantom reference):每次垃圾回收时都会被回收,主要用于监测对象是否已经从内存中删除。

  • with all references: 从GC Roots节点到该对象的引用路径,包含所有引用类型。
  • exclude weak references:从该对象到GC Roots节点的最短引用路径,去除弱引用。
  • exclude soft references:从该对象到GC Roots节点的最短引用路径,去除软引用。
  • exclude pahantorn references:从该对象到GC Roots节点的最短引用路径,去除虚引用。
  • exclude weak/soft references:从该对象到GC Roots节点的最短引用路径,去除弱引用,软引用。
  • exclude phantom/soft references:从该对象到GC Roots节点的最短引用路径,去除虚引用,软引用。
  • exclude phantom/weak references:从该对象到GC Roots节点的最短引用路径,去除虚引用,弱引用。
  • exclude all phantom/weak/soft etc. references:从该对象到GC Roots节点的最短引用路径,去除虚引用,弱引用,软引用。
  • exclude custom references:从该对象到GC Roots节点的最短引用路径,去除自定义引用。
  • Merge Shortest Paths to GC Roots: 从GC Roots到对象的共同路径。

  • Java Basics:

  • References: 显示引用和对象的统计信息,列出类加载器,包括定义的类
  • Class Loader Explorer: 列出选定对象的类装载器,包括其定义的类 。
  • Customized Retained Set: 计算选中对象的保留堆,排除指定的引用。
  • Group By Value: 按对象的字符串表示形式对其进行分组。
  • Open In Domainator Tree: 对选中对象生成支配树。
  • Show As Histogram: 展示任意对象的直方图。
  • leak Identification:内存泄露识别。
  • Export Snapshot: 导出快照信息。
  • Immediate Dominators: 查看某个对象的dominator
  • Show Retained Set: 计算一个对象的保留堆大小
  • Copy: 拷贝一些属性。
  • Search Queries: 搜索查询相关。

2.2 Histogram视图

MAT-Actions-Histogram.png

进入Histogram视图

  • 工具栏中点击Histogram按钮(区域三常用工具栏的第二个按钮)。


    工具栏进入Historgram.png
  • Overview页面的Actions部分有进入Histogram视图的快捷方式。


    Overview进入Histogram.png

Histogram视图使用

       Histogram视图从Class类的维度展示每个Class类的实例存在的个数、 占用的Shallow内存和Retained内存大小。

       咱们从Histogram视图可以看出,哪个Class类的对象实例数量比较多,以及占用的内存比较大,不过,多数情况下,在Histogram视图看到实例对象数量比较多的类都是一些基础类型,如char[](因为其构成了String)、String、byte[],所以仅从这些是无法判断出具体导致内存泄露的类或者方法的,可以使用 List objects 或 Merge Shortest Paths to GC roots 等功能继续钻取数据。如果Histogram视图展示的数量多的实例对象不是基础类型,是有嫌疑的某个类,如项目代码中的bean类型,那么就要重点关注了。

       如果存在内存溢出,时间久了溢出类的实例数量或者内存占比会越来越多,排名也越来越靠前的。可以点击工具类上的对比图标进行对比,通过多次对比不同时间点下的直方图对比就很容易把溢出的类找出来。

       每个类的详细信息(鼠标右键某个类的时候弹出框)

  • List objects:
  • with ontgoing references:查看当前类的所有对象,并且列出这些对象持有的外部对象引用。
  • with incoming references:查看当前类的所有对象,并且列出这些对象被那些外部对象所引用。
  • Show objects by class
  • with ontgoing references: 查看这个对象类型持有的外部对象引用
  • with ontgoing references: 查看这个对象类型被哪些外部对象引用
  • Merge Shortest Paths to GC Roots: 从GC Roots到对象的共同路径。

  • Java Basics:

  • References: 显示引用和对象的统计信息,列出类加载器,包括定义的类
  • Class Loader Explorer: 列出选定对象的类装载器,包括其定义的类 。
  • Customized Retained Set: 计算选中对象的保留堆,排除指定的引用。
  • Group By Value: 按对象的字符串表示形式对其进行分组。
  • Open In Domainator Tree: 对选中对象生成支配树。
  • Show As Histogram: 展示任意对象的直方图。
  • Java Collections
  • Array Fill Ratio: 输出数组中,非基本类型、非null对象个数占数组总长度的比例。
  • Arrays Grouped By Size: 显示数组的直方图,按大小分组。
  • leak Identification:内存泄露识别。
  • Export Snapshot: 导出快照信息。
  • Immediate Dominators: 查看某个对象的dominator
  • Show Retained Set: 计算一个对象的保留堆大小
  • Copy: 拷贝一些属性。
  • Search Queries: 搜索查询相关。
  • Calculate Minimum Retained Size(quick approx.): 计算最小的Ratined Size。
  • Calculate Precise Ratined Size: 精确计算Ratined Size。

2.3 Dominator Tree视图

MAT-Actions-Dominator Tree.png

进入Dominator Tree视图

  • 工具栏中点击Dominator Tree按钮(区域三常用工具栏的第三个按钮)。


    工具栏进入Dominator Tree.png
  • Overview页面的Actions部分有进入Dominator Tree视图的快捷方式。


    Overview进入Dominator Tree.png

Dominator Tree视图使用

       Dominator Tree视图中列出了每个对象(Object Instance)与其引用关系的树状结构,同时包含了占用内存的大小和百分比。通过Dominator Tree视图可以很容易的找出占用内存最多的几个对象(根据Retained Heap或Percentage排序)。Histogram视图和Dominator Tree视图都是可以用来帮助我们定位溢出源的。前者是基于类的角度,后者是基于对象实例的角度。Dominator Tree视图可以更方便的看出其引用关系。

2.4 Top Consumers视图

进入Top Consumers视图

  • Overview页面的Actions部分有进入Top Consumers视图的快捷方式。


    Overview进入Top Consumers.png

Top Consumers视图使用

       Top Consumers视图以图形化的方式列出最大的object,可以按照object、class、classloader和package进行group by。说白了就是方便我们通过不同的方式站到占内存最大的对象。

  • 按照对象查看内存占用


    MAT-Actions-Top Consumers(Objects).png
  • 按照类查看内存占用


    MAT-Actions-Top Consumers(Classes).png
  • 按照类加载查看内存占用


    MAT-Actions-Top Consumers(Class Loaders).png
  • 按照包名查看内存占用(根据包我们知道哪些公共用的到jar或自己的包占用。这样就可以看到包和包中哪些类的占用比较高)


    MAT-Actions-Top Consumers(packages).png

2.5 Duplicate Classes视图

MAT-Actions-Duplicate Classes.png

进入Duplicate Classes视图

  • Overview页面的Actions部分有进入Duplicate Classes视图的快捷方式。


    Overview进入Duplicate Class.png

Duplicate Classes视图使用

       Duplicate Classes视图列出了被加载多次的类,结果按类加载器进行分组,目标是加载同一个类多次被类加载器加载。使用Duplicate Classes视图很容易找到部署应用的时候使用了同一个库的多个版本的问题。

三 MAT报告

3.1 Leak Suspects(内存泄露报告)

MAT-Reports-Leak Suspects.png

Leak Suspects进入

  • 使用MAT打开一个dump文件的时候,会弹出向导菜单,保持默认选项,点Finish,就会导向 Leak Suspects内存泄露报告页面。


    打开文件进入Leak Suspects.png
  • 工具栏中点击Run Expect System Test > Leak Suspects按钮(区域三常用工具栏的第六个按钮)。


    工具栏进入Leak Suspects.png
  • Overview页面的Reports部分有进入Leak Suspects的快捷方式


    Overview进入Leak Suspects.png

Leak Suspects使用

       Leak Suspects 列出了MAT帮我们分析的可能有内存泄露嫌疑的地方。MAT工具分析了heap dump文件之后非常直观的展示了一个饼图,饼图深色区域被怀疑有内存泄漏的地方。而且下面会给出对怀疑内存泄露地方的具体描述信息。

       针对MAT帮我们分析出来的可能有内存泄露的地方。我们也可以进入查看怀疑地方的详细信息(Leak Suspects如果有怀疑的地方)。


MAT-Reports-Leak Suspects(In Detail).png
  • Description: 对怀疑内存泄露地方的一个描述信息。


    MAT-Reports-Leak Suspects(detail-description).png
  • Shortest Paths To the Accumulation Point: 展示怀疑内存泄露对象的Path to GC Roots(就是持有可能泄漏内存对象的最近一层)。这个视图的作用是可以分析是由于和哪个GC root相连导致当前Retained Heap占用相当大的对象无法被回收。由于是分析内存泄露的报告,找到导致当前对象无法被回收的GC roots,分析这些GC roots是否合理,是有必要的。


    MAT-Reports-Leak Suspects(detail-Paths To Point).png
  • Accumulated Objects in Dominator Tree:以对象的维度展示了以怀疑对象为根的Dominator Tree支配树。 可以方便的看出受当前对象“支配”的对象中哪个占用Retained Heap比较大。


    MAT-Reports-Leak Suspects(detail-Object Domainator Tree).png
  • Accumulated Objects by Class in Dominator Tree:展示了以对象对象为根的Dominator Tree支配树,并以Class类分组。


    MAT-Reports-Leak Suspects(detail-Class Dominator Tree ).png
  • All Accumulated Objects by Class:列举了怀疑对象所存储的所有内容。


    MAT-Reports-Leak Suspects(detail-Class).png

3.2 Top Components

Top Components进入

  • 工具栏中点击Run Expect System Test > Top Components按钮(区域三常用工具栏的第六个按钮)。


    工具栏进入Top Conponents.png
  • Overview页面的Reports部分有进入Top Components的快捷方式


    Overview进入Top Conponents.png

Top Components使用

       可以针对那些占用堆内存超过整个堆内存1%大小的组件做一系列的分析。

MAT-Reports-Top Components.png

       如上图所示,列出报告中总内存占用大于1%的组件。点击每个组件。有可以查看每个组件的详细信息。如下图所示(点击组件之后进入):

Top Components Summary.png
  • 饼图:展示内存占用大小。
  • Top Consumers:以图形化的方式列出最大的object,上文中有讲到Top Consumers哦
  • Retaines Set:是这个对象本身和他持有引用的对象和这些对象的retained set所占内存大小的总和。
  • Possible Memory Waste:可能的内存垃圾。有一下几个部分。
  • Duplicate Strings: 重复的字符串。
  • Empty Collections: 空集合。
  • Collection Fill Ratios: 集合使用率。
  • Miscellaneous:
  • Soft Reference Statistics: 软引用统计。
  • Weak Reference Statistics: 弱引用统计。
  • Finalizer Statistics: Finalizer统计(设计Java Finalizer的使用)。
  • Map Collision Ratios: Map碰撞比例。

Leak Suspects用于查找内存泄漏问题,Top Components负责分析占用堆内存超过整个堆内存1%大小的组件。

四 线程视图

       线程视图首先给出了在生成快照那个时刻,JVM中的Java线程对象列表。

进入线程视图

  • 工具栏中点击线程视图按钮。


    工具栏进入Thread.png

线程视图的使用

       在线程视图这个表中,可以看到以下几个信息:线程对象的名字、线程名、线程对象占用的堆内存大小、线程对象的保留堆内存大小、线程的上下文加载器、是否为守护线程。

MAT-Threads.png

       选中某个线程对象展开,可以看到线程的调用栈和每个栈的局部变量,通过查看线程的调用栈和局部变量的内存大小,可以找到在哪个调用栈里分配了大量的内存。

MAT-Threads(stack).png

       上面我们仅仅是对MAT工具做了一个简单的介绍,后续我们会根据一些实例,结合MAT的使用。做进一步的介绍。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容