当前位置: 首页 > news >正文

【JVM】分析Dump日志的工具EclipseMAT

【JVM】分析Dump日志的工具EclipseMAT

  • 【一】初始配置
    • 【1】环境配置
    • 【2】基础概念
  • 【二】各个功能介绍
    • 【1】Overview(总览面板)
      • (1)Details 概览区
      • (2)Actions 快捷工具(高频使用)
      • (3)Reports 报告区
      • (4)Inspector 对象详情面板
    • 【2】Histogram(直方图)
      • (1)打开方式
      • (2)功能描述
      • (3)案例
      • (4)菜单关键选项
    • 【3】Dominator Tree(支配树)定位内存根源持有者
      • (1)打开方式
      • (2)功能描述
      • (3)案例
      • (4)右键功能
    • 【4】Group分组功能
    • 【5】Thread Overview
    • 【6】List objects
      • (1)with outgoing references
      • (2)with incoming references
    • 【7】Path to GC Roots && Merge Shortets Paths to GC roots
      • (1)Paths to GC Roots
      • (2)Merge Shortest Paths to GC roots
      • (3)菜单选项
    • 【8】Leak Suspects Report 泄漏嫌疑自动报告(新手一键分析)
    • 【9】Class Loader Explorer 类加载器专属视图
      • (1)打开方式
      • (2)功能描述
    • 【10】GC Roots 根路径分析(判断对象是否满足 GC 条件)
  • 【三】使用案例
    • 【1】Leak Suspects:泄漏嫌疑报告(最常用)
  • 【四】# 关键区分易混淆选项

【一】初始配置

【1】环境配置

(1)要求JDK version >=17
(2)heap.hprof文件往往比较大,需要修改MemoryAnalyer.ini文件中设置

-vmargs-Xmx26g-Xms4g-XX:+UseG1GC-XX:+UseCompressedOops-XX:MaxGCPauseMillis=500-XX:+DisableExplicitGC-Dsun.rmi.dgc.client.gcInterval=3600000

【2】基础概念

  1. Shallow Heap(浅堆)
    对象本身占用内存,不包含引用的其他对象;比如DelegatingClassLoader自身对象几十字节。
  2. Retained Heap(保留堆)
    该对象一旦被 GC 回收,能连带释放的全部内存总和;判断内存泄漏最核心指标。
  3. Histogram(直方图):按类统计实例数、浅堆、保留堆,快速定位数量爆炸类(如大量DelegatingClassLoader)。
  4. Dominator Tree(支配树):找出占用内存最大的 “罪魁对象”,支配对象存活则所有下级对象都无法 GC。
  5. Leak Suspects Report(泄漏嫌疑报告):MAT 自动分析生成的一键诊断报告,新手首选。
  6. Incoming References(入引用)谁持有当前对象的强引用(你之前 DCL 泄漏最关键视图,找阻断 GC 的引用链)。
  7. Outgoing References(出引用):当前对象持有哪些其他对象。

【二】各个功能介绍

【1】Overview(总览面板)

页面分为 4 大区块,快速掌握整体内存状态:

(1)Details 概览区

  • Heap Size:dump 时总堆内存、已使用内存;
  • Number of Objects:堆内全部对象总数;
  • Class Loaders:统计所有类加载器数量(直接看有多少 DelegatingClassLoader、RestartClassLoader);
  • Unreachable Objects Histogram:已经没有强引用、等待 GC 回收的对象,数量大说明内存碎片多。

(2)Actions 快捷工具(高频使用)

表格

快捷按钮对应功能适用场景(你的 DCL 泄漏场景)
Histogram直方图视图统计DelegatingClassLoader总实例数、GeneratedMethodAccessor数量
Dominator Tree支配树找到 MybatisMybatisConfiguration这个大对象,它支配所有反射 Method、DCL
Top Consumers内存消耗 TOP 对象查看占用内存最高的单例 Bean(SqlSessionFactory、ReflectorFactory)
Duplicate Classes重复类检测热部署场景RestartClassLoader重复加载同一 PO 类,成倍产生 DCL

(3)Reports 报告区

  • Leak Suspects:自动识别内存泄漏点,给出完整引用链;泄漏嫌疑报告(最常用);
  • Component Report:按 ClassLoader 分组统计,单独看 AppClassLoader/DelegatingClassLoader 内存占用;
  • Top Components Report:超大组件内存分析(Mybatis 配置、Spring 容器);

(4)Inspector 对象详情面板

选中任意对象,底部自动展示:

  • Class Name:类全限定名;
  • Shallow/Retained 堆大小;
  • 字段列表:该对象所有成员变量(定位reflectorFactoryconfiguration引用)。

通过 File > Open Heap Dump… 打开dump文件,最先展示就是Overview概述界面,可以对Heap Dump有一个大致的了解,并提供了一些视图、报告的入口,这些视图、报告都对分析Heap Dump很有帮助,后续会介绍。

鼠标移动到饼图某个区域上方,在左侧会看到对象的详细信息,如左上方的 Inspector 展示了如:对象hashcode、类名、包名、Class类对象、父类、类加载器、shallow size、retained size、GC root类型。左下方展示了对象的一些属性信息、类层级信息。

【2】Histogram(直方图)

(1)打开方式

以下方式可以打开Histogram柱状图:
(1)点击Overview页面Actions区域内的“Histogram视图”链接

(2)点击工具栏的“histogram按钮”

(2)功能描述

列含义

  1. Class Name:类名,支持正则搜索DelegatingClassLoaderGeneratedMethodAccessor
  2. Objects:该类实例总数(你最关心的 DCL 数量在这里直接看);
  3. Shallow Heap:所有实例自身占用总内存;
  4. Retained Heap:回收该类所有实例可释放总内存。

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

(3)案例

(4)菜单关键选项

  1. List objects → with incoming references
    【重中之重】显示所有指向当前对象的强引用链,就是你截图里的完整链路:
    GeneratedMethodAccessor → DelegatingMethodAccessorImpl → Method → MethodInvoker → Reflector → DefaultReflectorFactory → MybatisConfiguration
    用来定位谁锁住 DCL 导致无法 GC,元空间泄漏核心操作。
  2. List objects → with outgoing references
    查看当前对象持有哪些下级对象,比如查看 Reflector 缓存了多少 Method。
  3. Show as Histogram / Show as Pie Chart
    饼图可视化内存占比,直观看到 Mybatis 缓存占用大头。
  4. Filter:过滤实例数、内存阈值,过滤掉小对象,只看爆炸增长的类。
  5. Merge Shortest Paths to GC Roots
    一键提取最短 GC 根引用链,直接找到 Spring 单例、静态变量、线程等根对象,跳过冗长中间链路。
  6. Group by → Class Loader
    按类加载器分组统计,区分:AppClassLoader、DelegatingClassLoader、热部署 RestartClassLoader,清晰看到每个加载器分别创建了多少对象。

【3】Dominator Tree(支配树)定位内存根源持有者

支配对象:如果 A 对象存活,B 对象永远无法被 GC,称 A 支配 B。

(1)打开方式

以下方式可以打开Dominator Tree视图:
(1)点击Overview页面Actions区域内的“Dominator Tree视图”链接

(2)点击工具栏的“Dominator Tree按钮” ,为整个堆打开一个支配树视图

(2)功能描述

列含义

  • Class Name:对象类型;
  • Retained Heap:该对象支配的总内存;
  • Percentage:占堆总内存比例。

该视图以实例对象的维度展示当前堆内存中Retained Heap占用最大的对象,以及依赖这些对象存活的对象的树状结构。视图中展示了实例对象名、Shallow Heap大小、Retained Heap大小、以及当前对象的Retained Heap在整个堆中的占比。

点开Dominator Tree实例对象左侧的“+”,会展示出下一层(next level),当所有引用了当前实例对象的引用都被清除后,下一层列出的objects就会被垃圾回收

这也阐明了“支配”的含义:父节点的回收会导致子节点也被回收,即因为父节点的存在使得子节点存活

Dominator Tree支配树可以很方便的找出占用Retained Heap内存最多的几个对象,并表示出某些objects的是因为哪些objects的原因而存活,在之后的 Dominator Tree概念 部分会对支配树做更详细的说明和举例

(3)案例

直接找到根支配对象

(4)右键功能

  • Merge Shortest Paths to GC Roots:直达 GC 根(Spring 容器);
  • Show Retained Set:展开所有被该对象锁住的下级对象,批量查看所有 DCL 实例。

【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分析,看到线程栈帧中的本地变量,在左下方的对象属性区域还能看到本地变量的属性,真的很方便

publicclassTestThreadOverview{privateStringstr1="str1";privateStringstr2="str2";publicstaticvoidmain(String[]args){TestThreadOverviewtest=newTestThreadOverview();Stringlocal_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

(1)with outgoing references

查看当前对象持有的外部对象引用(在对象关系图中为从当前对象指向外的箭头)

例如上面Thread Overview的例子代码中,查看main方法中第6行中的:TestThreadOverview test = new TestThreadOverview();
outgoing references查询结果为:

可以看到TestThreadOverview对象存在3个引用,第一个是TestThreadOverview的Class类对象,因为所有Java类都继承自java.lang.Object,所以都有class对象的引用,后两个是成员变量str1、str2

即列出了当前main方法中的局部变量TestThreadOverview所持有的所有外部对象引用

(2)with incoming references

查看当前对象被哪些外部对象所引用(在对象关系图中为指向当前对象的箭头)

例如上面Thread Overview的例子代码中,查看main方法中第6行中的:TestThreadOverview test = new TestThreadOverview();
incoming references查询结果为:

可以看到TestThreadOverview是main线程的一个本地局部变量,main线程本身还是一个GC root,而main线程在某个ThreadGroup中

【7】Path to GC Roots && Merge Shortets Paths to GC roots

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查询

(1)Paths to GC Roots

从当前对象到GC roots的路径,这个路径解释了为什么当前对象还能存活,对分析内存泄露很有帮助,这个查询只能针对单个对象使用

(2)Merge Shortest Paths to GC roots

从GC roots到一个或一组对象的公共路径

(3)菜单选项

Path to GC roots 和 Merge shortest Paths to GC roots 这两个查询都有很多选项,如:

意思是在查询到GC root的路径时,是包含所有引用,还是排除一些类型的引用(如软引用、弱引用、虚引用),从GC角度说,一个对象无法被GC,一定是因为有强引用存在,其它引用类型在GC需要的情况下都是可以被GC掉的,所以可以使用 exclude all phantom/weak/soft etc. references 只查看GC路径上的强引用

【8】Leak Suspects Report 泄漏嫌疑自动报告(新手一键分析)

使用MAT打开一个Dump文件时,会弹出向导窗口,保持默认选项,点Finish,就会导向 Leak Suspects内存泄露报告页面,MAT 自动扫描 dump,把高风险泄漏点分优先级展示,分为 3 部分:

  1. Suspect Summary 泄漏摘要
    列出 TOP3 嫌疑泄漏点,描述问题、预估可释放内存;你的 dump 会标记:大量GeneratedMethodAccessor被 Mybatis 反射缓存持有,导致元空间 ClassLoader 堆积。
  2. Suspect Details 详情
    自动生成精简引用链,不用手动逐层展开;
  3. Comparison Report
    支持对比两个不同时间的 dump,观察哪些类实例持续增长(对比前后 dump,DCL 数量持续上涨直接实锤泄漏)。

功能:加载.hprof堆快照文件,加载后弹出选择界面:

  • Leak Suspects Report(默认推荐):自动生成泄漏分析报告,适合快速排查元空间泄漏、OOM、堆溢出;
  • Component Report:按业务组件、类加载器分组分析内存;
  • 取消勾选:仅打开空白工作台,手动打开 Histogram/Dominator Tree。

如果打开Dump时跳过了的话,也可以从其它入口进入,如

(1)工具栏上的 Run Expect System Test > Leak Suspects

(2)Overview页面的Reports部分

Leak Suspects 是MAT帮我们分析的可能有内存泄露嫌疑的地方,可以体现出哪些对象被保持在内存中,以及为什么它们没有被垃圾回收

MAT提供了一个很贴心的功能,将报告的内容压缩打包到一个zip文件,并放在原始堆转储文件的目录下,一般命名为“xxx_Leak_Suspects.zip”,xxx是dump文件的名字,如果需要和同事一起分析这个内存问题的话,只需要把这个小小的zip包发给他就可以了,不需要把整个堆文件发给他。并且整个报告是一个HTML格式的文件,用浏览器就可以轻松打开

【9】Class Loader Explorer 类加载器专属视图

(1)打开方式

(2)功能描述

按 ClassLoader 树形展示所有加载的类、实例

  1. 树形分层展示:BootClassLoader → ExtClassLoader → AppClassLoader → DelegatingClassLoader;
  2. 统计每个 ClassLoader 加载了多少类、对象、占用元空间;
  3. 右键单个 DelegatingClassLoader:
    • List all Classes:查看该加载器加载的所有GeneratedMethodAccessor动态类;
    • Show GC Roots:查看这个 DCL 被谁强引用,判断能否回收。

单独筛选所有DelegatingClassLoader实例,统计总数,区分业务 ClassLoader 和反射专属加载器,直观看到 Mybatis 缓存创建了几千个 DCL。

【10】GC Roots 根路径分析(判断对象是否满足 GC 条件)

打开方式:任意对象右键 →Merge Shortest Paths to GC Roots

(1)GC Roots 类型(阻断 DCL 回收的常见根)

  1. Static Fields:静态全局缓存(Mybatis DefaultReflectorFactory 是静态单例);
  2. Thread:线程池核心线程、定时任务线程持有上下文 ClassLoader;
  3. System Class:JDK 系统类(ReflectionFactory 全局缓存);
  4. Local Variable:方法内未释放的局部变量(长期存活线程的 ThreadLocal)。

(2)判断标准(对应你之前 DCL GC 三条件)

  • 若 GC Roots 路径存在业务静态 / 单例 Bean→ DCL 存在永久强引用,不满足 GC 条件;
  • 若仅存在ReflectionFactoryWeakHashMap 弱引用,无其他 GC 根 → 满足 GC,Full GC 后可回收。

【三】使用案例

【1】Leak Suspects:泄漏嫌疑报告(最常用)

【四】# 关键区分易混淆选项

  1. with incoming referencesvswith outgoing references
    • incoming:谁引用我(找泄漏根源,必用);
    • outgoing:我引用谁(看缓存存了多少下级对象)。
  2. Shallow Heap vs Retained Heap
    • Shallow:对象本身大小,无参考价值;
    • Retained:回收该对象能释放的总内存,判断泄漏严重程度。
  3. Histogram vs Dominator Tree
    • Histogram:按统计实例数量(查 DCL 总数);
    • Dominator Tree:按单个对象统计支配内存(找根单例 Bean)。
  4. Merge Shortest Paths to GC Roots
    过滤多层中间无用对象,直接展示从 GC 根到目标 DCL 的最短链路,简化分析。
http://www.jsqmd.com/news/1229513/

相关文章:

  • 构建线程安全渲染系统:六大核心组件与C++多线程实践
  • v-hotkey插件开发:如何扩展自定义快捷键功能与修饰符
  • 鸿蒙Flutter ProxyProvider代理Provider:依赖其他Provider的状态
  • iOS激活锁绕过工具applera1n:技术原理与实用指南
  • C#模式匹配实战:8大技巧优化代码逻辑
  • Claude Desktop Linux终极指南:5分钟搞定跨发行版AI助手部署
  • 2026南昌贵金属回收排名 TOP5 国家资质黄金回收、铂金回收、白银回收,上门回收无套路靠谱 联系方式推荐 - 中安检金银铂钻回收
  • java学习交流
  • 雅马哈乐器滞销事件背后的行业变革与技术解析
  • 2026杭州别墅阳光房改造多家行业标杆厂家考察避坑 - 中国远见品牌企业资讯
  • 从Excel公式到自动决策:AI办公工具进阶路线图(附:21个真实场景Prompt模板+权限配置Checklist)
  • SpringBoot+Vue全栈项目实战:家政服务平台从部署到二次开发指南
  • 【Springboot毕设全套源码+文档】基于springboot旧物回收商城系统的设计与实现(丰富项目+远程调试+讲解+定制)
  • 深入解析CPTS事件FIFO:高精度时间同步的硬件机制与软件实践
  • 2026九江贵金属回收排名 TOP5 国家资质黄金回收、铂金回收、白银回收,上门回收无套路靠谱 联系方式推荐 - 中安检金银铂钻回收
  • Krakatau字节码工程实践:深度解析Java字节码汇编与反汇编技术
  • ROCm GPU内存管理终极指南:从零到精通的高性能内存优化策略
  • 福州高定木作避坑:全屋定制最容易踩的 3 个隐形陷阱
  • 食品饮料经销商如何通过订货小程序提高客户下单效率
  • 2026年7月洛阳靠谱的刑事辩护律师推荐指南:焦艺昊拆解跑分、醉驾、贷款诈骗案件司法处置核心实务要点 - 十大排行榜推荐
  • 2026企业官网GEO怎么优化?三阶方法提收录,零成本提30%抓取权重附自查清单
  • GitHub 全网最全使用指南:从入门到榨干
  • SpringBoot集成bpmn-js流程设计器:前端可视化工作流开发实战
  • AI数据分析效率翻倍的7个隐藏技巧:90%的数据工程师至今未掌握的自动化工作流
  • tkDNN性能调优秘籍:如何将Jetson Xavier NX的推理速度提升3倍
  • AI教材写作秘籍:掌握这些技巧,用AI快速完成高校专业教材编写!
  • 本地黄金回收怎么选,天津正规靠谱高价门店推荐 - 日常比对手册
  • InSPyReNet项目深度解析:图像金字塔结构如何革新显著目标检测
  • 4小时完成8xA100实验:ddpo-pytorch的高性能训练策略与配置分享
  • 循环工程:从代码编写到自动化系统设计的范式转变