概述

MAT(Memory Analyzer Tool)工具是一款功能强大的]ava堆内存分析器。可以用于查找内存泄漏以及查看内存消耗情况。MAT是基于Eclipse开发的,不仅可以单独使用,还可以作为插件的形式嵌入在Eclipse中使用。是一款免费的性能分析工具,使用起来非常方便。大家可以在https://www.eclipse.org/mat/downloads.php下载并使用MAT。

!

MAT可以分析heap dump文件。在进行内存分析时,只要获得了反映当前设备内存映像的hprof文件,通过MAT打开就可以直观地看到当前的内存信息。一般说来,这些内存信息包含:所有的对象信息,包括对象实例、成员变量、存储于栈中的基本类型值和存储于堆中的其他对象的引用值。所有的类信息,包括classloader、类名称、父类、静态变量 GCRoot到所有的这些对象的引用路径线程信息,包括线程的调用栈及此线程的线程局部变量(TLS)

缺点:MAT不是一个万能工具,它并不能处理所有类型的堆存储文件。但是比较主流的厂家和格式,例如SuN,HP,SAP所采用的HPROF二进制堆存储文件,以及IBM的PHD堆存储文件等都能被很好的解析。

最吸引人的还是能够快速为开发人员生成内存泄漏报表,方便定位问题和分析问题。虽然MAT有如此强大的功能,但是内存分析也没有简单到一键完成的程度,很多内存问题还是需要我们从MAT展现给我们的信息当中通过经验和直觉来判断才能发现

如何获取dump文件

方法一:通过前一章介绍的jmap工具生成,可以生成任意一个java进程的dump文件;

方法二:通过配置VM参数生成。选项"-XX:+HeapDumpOnOutOfMemoryError"或"-XX:+HeapDumpBeforeFullGC"选项"-XX:HeapDumpPath"所代表的含义就是当程序出现OutofMemory时,将会在相应的目录下生成一份dump文件。如果不指定选项“-XX:HeapDumpPath”则在当前目录下生成dump文件。对比:考虑到生产环境中几乎不可能在线对其进行分析,大都是采用离线分析,因此使用jmap+MAT工具是最常见的组合。
方法三:使用VisualVM可以导出堆dump文件

方法四:使用MAT既可以打开一个已有的堆快照,也可以通过MAT直接从活动]aVa程序中导出堆快照。该功能将借助jps列出当前正在运行的]ava进程,以供选择并获取快照。

分析 dump文件

histogram

具体内容:

MAT的直方图和jmap的-histo子命令一样,都能够展示各个类的实例数目以及这些实例的Shallowheap总和。但是,MAT的直方图还能够计算Retained heap,并支持基于实例数目或Retainedheap的排序方式(默认为Shallow heap)。此外,MAT还可以将直方图中的类按照超类、类加载器或者包名分组。当选中某个类时,MAT界面左上角的Inspector窗口将展示该类的Class实例的相关信息,如类加载器等。

thread overview

图标:

具体信息:

可通过该功能查看系统中的Java线程、查看局部变量的信息,获得对象的引用关系

with outgoing references

此对象引用了哪些对象,图示:

结果:

with incoming references

此对象被谁引用,图示:

结果:

浅堆与深堆

浅堆shallow heap

浅堆(Shallow Heap)是指一个对象本身所消耗的内存。在32位系统中,一个对象引用会占据4个字节,一个int类型会占据4个字节,long型变量会占据8个字节,每个对象头需要占用8个字节。根据堆快照格式不同,对象的大小可能会向8字节进行对齐。以String为例:2个int值共占8字节,对象引用占用4字节,对象头8字节,合计20字节,向8字节对齐,故占24字节。(jdk7中)

这24字节为String对象的浅堆大小。它与String的value实际取值无关,无论字符串长度如何,浅堆大小始终是24字节。对象头代表根据类创建的对象的对象头,还有对象的大小不是可能向8字节对齐,而是就向8字节对齐

深堆retained heap

保留集(Retained Set):
对象A的保留集指当对象A被垃圾回收后,可以被释放的所有的对象集合(包括对象A本身),即对象A的保留集可以被认为是只能通过对象A被直接或间接访问到的所有对象的集合。通俗地说,就是指仅被对象A所持有的对象的集合。
深堆(Retained Heap):
深堆是指对象的保留集中所有的对象的浅堆大小之和。
注意:浅堆指对象本身占用的内存,不包括其内部引用对象的大小。一个对象的深堆指只能通过该对象访问到的(直接或间接)所有对象的浅堆之和,即对象被回收后,可以释放的真实空间。

当前深堆大小 = 当前对象的浅堆大小 + 对象中所包含对象的深堆大小,如果对象包括的对象还有对象的话,也要算最里层的对象的大小

对象的实际大小

另外一个常用的概念是对象的实际大小。这里,对象的实际大小定义为一个对象所能触及的所有对象的浅堆大小之和,也就是通常意义上我们说的对象大小。与深堆相比,似乎这个在日常开发中更为直观和被人接受,但实际上,这个概念和垃圾回收无关。下图显示了一个简单的对象引用关系图,对象A引用了C和D,对象B引用了C和E。那么对象A的浅堆大小只是A本身,不含C和D,而A的实际大小为A、C、D三者之和。而A的深堆大小为A与D之和,由于对象C还可以通过对象B访问到,因此不在对象A的深堆范围内。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b8NBCwgU-1637481649886)(https://gitee.com/lydon/cloudimages/raw/master/images/Image(89)].png)

示例一

A对象的Retained size=A对象的Shallow sizeB对象的Retained size=B对象的Shallow size+C对象的Shallow Size这里不包括D对象,因为D对象被GC Roots直接引用。如果GC Roots不引用D对象呢?

B对象的Retained size=B对象的Shallow size+C对象的Shallow Size+D对象的Shallow Size

示例二

示例代码

package com.lydon.test;import java.util.ArrayList;
import java.util.List;/*** 有一个学生浏览网页的记录程序,它将记录 每个学生访问过的网站地址。* 它由三个部分组成:Student、WebPage和StudentTrace三个类**  -XX:+HeapDumpBeforeFullGC -XX:HeapDumpPath=c:\code\student.hprof* @author shkstart* @create 16:11*/
public class StudentTrace {static List<WebPage> webpages = new ArrayList<WebPage>();public static void createWebPages() {for (int i = 0; i < 100; i++) {WebPage wp = new WebPage();wp.setUrl("http://www." + Integer.toString(i) + ".com");wp.setContent(Integer.toString(i));webpages.add(wp);}}public static void main(String[] args) {createWebPages();//创建了100个网页//创建3个学生对象Student st3 = new Student(3, "Tom");Student st5 = new Student(5, "Jerry");Student st7 = new Student(7, "Lily");for (int i = 0; i < webpages.size(); i++) {if (i % st3.getId() == 0)st3.visit(webpages.get(i));if (i % st5.getId() == 0)st5.visit(webpages.get(i));if (i % st7.getId() == 0)st7.visit(webpages.get(i));}webpages.clear();System.gc();}
}class Student {private int id;private String name;private List<WebPage> history = new ArrayList<>();public Student(int id, String name) {super();this.id = id;this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public List<WebPage> getHistory() {return history;}public void setHistory(List<WebPage> history) {this.history = history;}public void visit(WebPage wp) {if (wp != null) {history.add(wp);}}
}class WebPage {private String url;private String content;public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}
}

dump文件分析图

分析

student 对象占24个字节是=int(4)+String(4)+history(4)+对象头(8)=20 再对齐24
elementData数组的浅堆是80个字节,而elementData数组中的所有WebPage对象的深堆之和是1208个字节,所以加在一起就是elementData数组的深堆之和,也就是1288个字节
arraylist在容量不够时会进行当前长度的一半扩容,默认为10 ,第一次扩阵容为10+10/2=15
第二次扩容为15+15/2=22

解释

我说“elementData数组的浅堆是80个字节”,其中15个对象一共是60个字节,对象头8个字节,数组对象本身4个字节,这些的和是72个字节,然后总和要是8的倍数,所以“elementData数组的浅堆是80个字节”
我说“WebPage对象的深堆之和是1208个字节”,一共有15个对象,其中0、21、42、63、84、35、70不仅仅是7的倍数,还是3或者5的倍数,所以这几个数值对应的i不能计算在深堆之内,这15个对象中大多数的深堆是152个字节,但是i是0和7的那两个深堆是144个字节,所以(13152+1442)-(6*152+144)=1208,所以这也印证了我上面的话,即“WebPage对象的深堆之和是1208个字节”
因此“elementData数组的浅堆80个字节”加上“WebPage对象的深堆之和1208个字节”,正好是1288个字节,说明“elementData数组的浅堆1288个字节”

支配树

概念

支配树的概念源自图论。MAT提供了一个称为支配树(Dominator Tree)的对象图。支配树体现了对象实例间的支配关系。在对象引用图中,所有指向对象B的路径都经过对象A,则认为对象A支配对象B。如果对象A是离对象B最近的一个支配对象,则认为对象A为对象B的直接支配者。支配树是基于对象间的引用图所建立的,它有以下基本性质:·对象A的子树(所有被对象A支配的对象集合)表示对象A的保留集(retained set),即深堆。如果对象A支配对象B,那么对象A的直接支配者也支配对象B。支配树的边与对象引用图的边不直接对应。如下图所示:

左图表示对象引用图,右图表示左图所对应的支配树。对象A和B由根对象直接支配,由于在到对象C的路径中,可以经过A,也可以经过B,因此对象C的直接支配者也是根对象。对象F与对象D相互引用,因为到对象F的所有路径必然经过对象D,因此,对象D是对象F的直接支配者。而到对象D的所有路径中,必然经过对象C,即使是从对象F到对象D的引用,从根节点出发,也是经过对象C的,所以,对象D的直接支配者为对象C。
同理,对象E支配对象G。到达对象H的可以通过对象D,也可以通过对象E,因此对象D和E都不能支配对象H,而经过对象C既可以到达D也可以到达E,因此对象C为对象H的直接支配者。
跟随我一起来理解如何从“对象引用图—》支配树”,首先需要理解支配者(如果要到达对象B,毕竟经过对象A,那么对象A就是对象B的支配者,可以想到支配者大于等于1),然后需要理解直接支配者(在支配者中距离对象B最近的对象A就是对象B的直接支配者,你要明白直接支配者不一定就是对象B的上一级,然后直接支配者只有一个),然后还需要理解支配树是怎么画的,其实支配树中的对象与对象之间的关系就是直接支配关系,也就是上一级是下一级的直接支配者,只要按照这样的方式来作图,肯定能从“对象引用图—》支配树”

实例

在MAT中,单击工具栏上的对象支配树按钮,可以打开对象支配树视图。

该截图显示部分Lily学生的history队列的直接支配对象。即当lily对象被回收,也会一并回收的所有对象。显然能被3或者5整除的网页不会出现在该列表中,因为它们同时被另外两名学生对象引用。

堆分析实例

根据当前的session总数,可以计算每秒的平均压力为:9941/(1403324677648-1403324645728)*1000=311次/秒。由此推断,在发生Tomcat堆溢出时,Tomcat在连续30秒的时间内,平均每秒接收了约311次不同客户端的请求,创建了合计9941个session。

MAT(Memory Analyzer Tool)工具使用超详细版相关推荐

  1. 使用MAT(Memory Analyzer Tool)工具分析dump文件--转

    原文地址:http://gao-xianglong.iteye.com/blog/2173140?utm_source=tuicool&utm_medium=referral 前言 生产环境中 ...

  2. linux分析mat使用教程,使用MAT(Memory Analyzer Tool)工具分析dump文件

    <使用MAT(Memory Analyzer Tool)工具分析dump文件> 前言 生产环境中,尤其是吃大内存的JVM,一旦出现内存泄露等问题是非常容易引发OutofMemory的,如果 ...

  3. MAT(Memory Analyzer Tool)工具入门介绍

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 1.MA ...

  4. Java内存分析工具MAT(Memory Analyzer Tool)的介绍与使用

    详细介绍了Java内存分析工具MAT(Memory Analyzer Tool)的常见使用方法,MAT可以帮助Java程序员快速进行内存分析,定位问题. MAT(Memory Analyzer Too ...

  5. android matix滤镜,使用MAT (Memory Analyzer Tool)分析Andriod项目内存泄漏

    前言: 在上一篇文章介绍了如何使用Android Monitor分析项目查找内存泄漏 ,本篇将介绍如何使用MAT(Memory Analyzer Tool)来分析和查找项目中内存泄漏的地方 MAT介绍 ...

  6. Mac OS下MAT(Memory Analyzer Tool)安装与启动

    简述 MAT(Memory Analyzer Tool),内存分析工具,是一款常用的JVM调优工具,对于分析内存泄漏(Memory Leak)有奇效. 本文主要描述在Mac系统下,如何安装MAT及成功 ...

  7. MAT Memory Analyzer Tool 插件安装(图解)

    @author YHC 前段时间做了一个项目,Exception in thread "main" java.lang.OutOfMemoryError: Java heap sp ...

  8. jvm性能分析工具之-- Eclipse Memory Analyzer tool(MAT)

    性能分析工具之-- Eclipse Memory Analyzer tool(MAT)(一) 前言 性能分析工具之-- Eclipse Memory Analyzer tool(MAT)(一)中介绍了 ...

  9. 使用Memory Analyzer tool(MAT)分析内存泄漏(一)

    使用Memory Analyzer tool(MAT)分析内存泄漏(一) (2010年05月21日) 发表于 Java博客 前言的前言 :本文是自 2005 年 8 月以来,首次在一个月之内发布三篇文 ...

最新文章

  1. vb.net2019- 机器学习ml.net情绪分析(1)
  2. ----icon moon追加新字体图标----
  3. 钻石2 D2 让你的diamond2待机2天,甚至2天以上的方法(绝对不是购买电池)
  4. mysql数据库 day06
  5. IG击败TOP进入春季赛决赛 王思聪督战时吃玉米动作亮了
  6. 今日恐慌与贪婪指数为91 贪婪程度与昨日持平
  7. Pyston v2.0 发布,速度比 Python 快 20%!
  8. oracle系列(二)oracle体系结构和用户管理
  9. UVA 10474 Where is the Marble?
  10. Win7连接蓝牙耳机(千月蓝牙激活码分享)无需破解软件
  11. 数据库 组合主键 外键
  12. PHP小白编程学习——第三方登录功能设计思维
  13. Lacuncher3---修改文件夹图标和修改桌面布置
  14. Ambari2.7.4配置HIVE_AUX_JARS_PATH
  15. 删除有外键关联的表报错,Cannot delete or update a parent row: a foreign key constraint fails
  16. 优达学城 深度学习 任务3
  17. 服务器迁移需要备份哪些文件?
  18. 利用go-ethereum创建自己的以太坊账户
  19. 【Ybt OJ】[数学基础 第3章] 同余问题
  20. 一个简单的pingpong程序测试mpi消息通讯的开销及并行计算通讯启动时间测算

热门文章

  1. 哈理工OJ 1490 咒语(BFS广度优先搜索)
  2. 浏览器地址栏javascript
  3. 易基因文献速递|BS-miRNA-seq技术发现人类microRNA中CpG和 非CpG上的(h)m5C修饰
  4. 批量爬取巨潮资讯网中“贵州茅台”相关公告的PDF文件。
  5. React TSLint中常见的问题及处理方法
  6. axios是干什么的
  7. 由阿里IPO引发的思考:什么样的互联网公司才是好公司?
  8. win10 python3.8.10下ipython无响应处理
  9. 流浪的阿猫阿狗我要怎么帮助你?
  10. 国产化7K325T板卡学习资料: 基于国产化Ch-7K325T 的 FMC接口PCIe卡 国产化板卡