Memory Analyzer (MAT)
TIPS 本文基于MAT 1.10.0编写。该版本最低支持JDK 8
Memory Analyzer又名Memory Analyzer Tool,简称MAT,可以作为独立软件,也可作为Eclipse插件存在。它是一个快速且功能丰富的Java堆内存分析器,可帮助您查找内存泄漏并减少内存消耗。相关地址:
- 官方网站:https://www.eclipse.org/mat/
- 下载地址:https://www.eclipse.org/mat/downloads.php
- Wiki:https://wiki.eclipse.org/MemoryAnalyzer#Getting_a_Heap_Dump
- 使用文档: https://help.eclipse.org/2020-03/index.jsp ,点击左侧 Memory Analyzer 菜单
MAT的主要功能:
- 找出内存泄漏的原因
- 找出重复引用的类和jar
- 分析集合的使用
-
概念
Shallow vs. Retained Heap(浅堆与保留堆)
浅堆(Shallow Heap):一个对象消耗的内存。一个对象引用需要32或64 bit(取决于OS体系结构),每个Integer 4个字节,每个Long 8个字节等。根据堆转储格式,这个大小也可能会被调整(例如,对齐为8bit),从而更好地模拟VM的实际消耗量。
- X的保留集(Retained set):当X被垃圾回收时,由GC删除的对象集。同理,如果X没有被回收,那么该集合中的对象都会“保留下来”。
- X的保留堆(Retained heap):X的保留集中的所有对象的浅层大小的总和,即X保持活动的内存。换而言之,Retained heap指的是对象X的保留内存大小,即由于它的存活导致多大的内存没有被回收。
- 前导对象集的保留集(例如特定类的所有对象,或特定类加载器加载的所有类的所有对象,或者仅仅是一堆任意对象):前导对象不可达时,被释放的那些对象。
一般来说,对象的浅堆是对象在堆中的大小,而同一对象的保留大小是在垃圾回收对象时将释放的堆内存量。
Retained set包括这些对象以及只能通过这些对象访问的所有其他对象。保留大小是保留集中包含的所有对象的总堆大小。
TIPS
如图,A和B是GC Roots(例如:方法参数、局部变量,或者调用了wait()、notify()或synchronized()的对象)可以看出:
- E的存在,会导致G无法被回收,因此E的Retained set是E和G;
- C的存在,会导致E、D、F、G、H都无法被回收,因此C的Retined set是C、E、D、F、G、H;
- A和B的存在,会导致C、E、D、F、G、H都无法被回收,因此A和B的Retained set是A、B、C、E、D、F、G、H。
最小保留大小给出了良好的保留估计,其计算速度快于一组对象的确切保留大小。它仅取决于检查集中的对象数,而不取决于堆转储中的对象数。
Dominator Tree(支配树)
MAT提供了对象图的支配树。通过将对象参考图转换为支配树,您可以轻松地识别最大的保留内存块以及对象之间的依赖关系。下面是术语的非正式定义
- X支配Y:如果对象图中从起始(或Root)节点到Y的每条路径都必须经过X,那么就说对象X支配对象Y
- 直接支配者:某个对象路径最短的支配者
支配树是在对象图的基础上建立的,在支配树中,每个节点都是其子节点的直接支配者。因此,基于支配树可以轻松看出对象之间的依赖关系。
支配者树具有以下重要属性:
- 对象从属于X的子树(例如对象被X支配)就是X的Retained set也就是说,X节点的子树是所有被X支配的节点集合,也就是X的Retained set;
- 如果X是Y的直接支配节点,那么支配X的节点也可以支配Y
- 支配树中的边并不直接对应于对象图中的对象引用
使用
独立软件版本:前往 https://www.eclipse.org/mat/downloads.php ,根据自己的操作系统,下载安装即可使用。百度盘加速:
链接:https://pan.baidu.com/s/1HXjzNDpzin6fXGrZPyQeWQ 密码:aon2
Eclipse插件版本:在Eclipse插件中心安装即可使用。
欢迎页面
TIPS
来自朋友阿杜的文章 https://www.jianshu.com/p/9990fb95bb5a主要功能项
inspector:透视图,用于展示一个对象的详细信息,例如内存地址、加载器名称、包名、对象名称、对象所属的类的父类、对象所属的类的加载器对象、该对象的堆内存大小和保留大小,gc root信息。下半部分展示类的静态属性和值、对象的实例属性和值、对象所属的类的继承结构。
- Heap Dump History:列出最近分析过的文件
- 功能选择栏:从左到右依次是:概览、类直方图、支配树、OQL查询、线程视图、报告相关、详细功能。其中概览就是上图的这个页面,其他则提供了一些更细致的分析能力。总的来说,功能上和VisualVM大同小异,但分析得更加细致。
- 饼图:展示retained size对象占用比例
- Actions:常用的内存分析动作
- Histogram:列出内存中的对象,对象的个数及其大小。点击后生成的报表:
- Class Name : 类名称,java类名
- Objects : 类的对象的数量,这个对象被创建了多少个
- Shallow Heap :一个对象内存的消耗大小,不包含对其他对象的引用
- Retained Heap :是shallow Heap的总和,也就是该对象被GC之后所能回收到内存的总和
- Dominator Tree:列出最大的那些对象,以及他们为什么存活。
- Top Consumers:打印最昂贵的对象,以内和包分组
- Duplicate Classes:检测被多个classloader加载的类
- Histogram:列出内存中的对象,对象的个数及其大小。点击后生成的报表:
- Reports:报表
- Leak Suspects:自动分析内存泄漏的原因,并能直接定位到Class,找到可能导致内存泄露的代码行数。
- Top Components:列出占用超过1%的组件的报告信息
Step by Step:
- Top Components:分析从属于指定包或者class loader的对象。
个人遇到的问题
启动报如下异常:
解决方案:java.lang.IllegalStateException: The platform metadata area could not be written: /private/var/folders/xt/xkf315314t38ct3144c_wz4c0000gp/T/AppTranslocation/1B159134-8301-46AC-B119-CB67BA8452F6/d/mat.app/Contents/MacOS/workspace/.metadata. By default the platform writes its content
把mat.app挪到macOS的应用目录下并重启即可。当然也可修改 mat.app/Contents/Eclipse/MemoryAnalyzer.ini 。
参考文档:
- Top Components:分析从属于指定包或者class loader的对象。
- https://www.eclipse.org/forums/index.php/t/214452/
- https://github.com/cncgoko/Goko/issues/56
- https://www.vogella.com/tutorials/EclipseMemoryAnalyzer/article.html
https://community.bonitasoft.com/blog/acquire-heap-dump-mat-memory-analyzer-tool
拓展阅读
朋友的文章:
- MAT入门到精通(二)