Memory Analyzer (MAT) 在实际开发中的使用
文章目录
- Memory Analyzer (MAT) 在实际开发中的使用
- 概述
- 注意点
- 基本使用
- 检查概述
- 获取直方图
- View the Dominator Tree
- 到GC根的路径
- 使用示例
- 制作堆dump
- HeapDumpOnOutOfMemoryError
- Jmap 生成堆Dump
- Mat打开堆快照
- Histogram
- Thread Overview
- 执行内存泄露报告
- 列出大对象
- 查看对象占用树
- 元素介绍
- GcRoots
- Shallow Heap
- Retained set
- with incoming references
- with outgoing references
- 参考文献
概述
MAT
,全称Memory Analysis Tools
,是一款分析Java
堆内存的工具,可以快速定位到堆内泄漏问题。该工具提供了两种使用方式,一种是插件版,可以安装到Eclipse
使用,另一种是独立版,可以直接解压使用。
官网地址:Eclipse Memory Analyzer Open Source Project | The Eclipse Foundation
注意点
- 运行独立版本的内存分析器所需的最低
Java
版本是Java 17
,下载地址 https://pan.baidu.com/s/11IZ5m2D41r1S8Anu84H0ZQ?pwd=makq
- 如果堆文件实际大小很大比如
8G
,但是用Mat
打开后内存信息只有1G
,那么可以通过下面的设置显示无法访问对象的详细信息,需要删除之前导入进来的重新导入
基本使用
检查概述
- 通过文件> 打开堆转储…打开堆转储…查看概述页。 如果您有可用的堆转储,请立即尝试打开堆转储。
在右侧,您可以找到转储的大小和 类、对象和类装入器。
如果转储的总大小远小于 文件是可能的 堆转储包含许多垃圾 对象 在下一个垃圾桶时丢弃 收集。显示无法访问对象的步骤见注意点中描述的方法。
获取直方图
- 从工具栏中 直方图图标选择直方图图标以列出每个类的实例数, 浅尺寸(
ShallowHeap
)和保留尺寸(Retained Heap
)
-
浅堆是一个对象所消耗的内存,
X
的保留堆是X
的保留集合中所有对象的浅大小之和,即X
保留的存活内存。
View the Dominator Tree
- 支配树显示堆转储中最大的对象。树的下一层列出了那些对象,如果对父节点的所有传入引用被删除,这些对象将被垃圾收集。支配树是一种强大的工具,用于研究哪些对象使哪些其他对象保持存活。同样,树可以按照类加载器(例如组件)和包分组,以简化分析。
到GC根的路径
- 从对象到
GC
根的(反向)引用链——所谓的GC
根路径——解释了为什么对象不能被垃圾收集。该路径有助于解决Java
中的经典内存泄漏:这些泄漏的存在是因为即使程序逻辑不再访问对象,对象仍然被引用。
使用示例
制作堆dump
HeapDumpOnOutOfMemoryError
- 其实在很多时候我们是不知道何时会发生
OOM
,所以需要在发生OOM
时自动生成dump
文件。其实很简单,只需要在启动时加上如下参数即可。HeapDumpPath
表示生成dump文件保存的目录。
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\tmp
- 当系统堆溢出的时候会自动生成快照文件,项目上一般都会配置这个参数
- 内存溢出
Idea
显示如下:
java.lang.OutOfMemoryError: GC overhead limit exceeded
Dumping heap to java_pid25396.hprof ...
Heap dump file created [1486916275 bytes in 5.168 secs]
Jmap 生成堆Dump
- 首先要查找运行的
Java
程序的pid
,然后使用jmap
命令生成dump
文件。file
后面是保存的文件名称,1246
则是java
程序的PID
。
jmap -dump:format=b,file=user.dump 1246
Mat打开堆快照
- 模拟堆栈溢出,如下图所示,从图中可以看出大对象占用
800M
左右,RetainedSIze
占用637.4M
Histogram
- 列举类的实例信息,从这里面明显的可以看到,这个对象没有
GCRoot
而且占用比较大,很有可能是内存泄露的地方
Thread Overview
- 线程分析概览,展示出了所有的线程,主线程,以及各个线程中的浅堆和深堆占用的大小,类加载器,是否守护线程等信息
执行内存泄露报告
- 点击
Leak Suspects
查看存在内存泄露的地方
列出大对象
- 从下面的这个图可以判断出程序中存在死循环
查看对象占用树
- 在此视图中列出了每个对象(
Object Instance
)与其引用关系的树状结构,同时包含了占用内存的大小和百分比。通过Dominator Tree
视图可以很容易的找出占用内存最多的几个对象(根据Retained Heap
或Percentage
排序);
元素介绍
GcRoots
GC Root(Garbage Collection Root)
是指在Java
虚拟机中被直接或间接引用的对象集合,它们被认为是存活对象,不能被垃圾回收器回收。GC Root
的作用是为垃圾回收器提供一个初始的扫描位置,以便确定哪些对象是可达的,哪些对象是不可达的。垃圾回收器会从GC Root
开始扫描,并标记所有可达对象,最终将不可达对象回收掉。
GC Root
包括以下几种类型:
-
虚拟机栈中引用的对象
-
方法区中类静态属性引用的对象
-
方法区中常量引用的对象
-
Native
方法中引用的对象 -
活动线程中的对象
-
当前类加载器加载的类的对象
-
例如下面的图中
GCRoots
没有到达object5、object6、object7
,因此他们三标记为可以被回收
Shallow Heap
Shallow Heap
为对象自身占用的内存大小,不包括它引用的对象。
Retained set
- 对象本身和他持有引用的对象和这些对象的
retained set
所占内存大小的总和
with incoming references
- 对象
A
和对象B
持有对象C
的引用 - 对象
C
持有对象D
和对象E
的引用 - 对象
C
的Incoming References
:拥有对象C
的引用的所有对象都称为Incoming references
。在此示例中,对象C
的Incoming references
是对象A
、对象B
和C
的类对象
with outgoing references
- 对象
C
的Outgoing References
:对象C
引用的所有对象都称为Outgoing References
。在上面图中,对象C
的outgoing references
是对象D
、对象E
参考文献
- 一文让你理解什么是shallow heap及retained heap - 知乎 (zhihu.com)
- Shallow Heap 和 Retained Heap的区别_shallow heap和retained heap什么区别-CSDN博客
- JVM 内存分析神器 MAT: Incoming Vs Outgoing References 你真的了解吗?-腾讯云开发者社区-腾讯云 (tencent.com)