MAT工具分析 Java 堆 dump 文件(mac系统为例)

发布于:2025-07-26 ⋅ 阅读:(28) ⋅ 点赞:(0)

一、安装与配置 Eclipse MAT

Eclipse Memory Analyzer Tool (MAT) 

1、下载

确保已安装 Java 8 或更高版本,并下载最新版 Eclipse MAT(官网链接)。

根据自己的电脑系统选择对应版本,我是mac m系列的系统,就选择下面的

2、安装

windows系统一般解压后直接运行可执行文件(如 MemoryAnalyzer.exe),默认下一步即可

mac系统安装更加简单,不过多赘述

3、调整参数

找到MemoryAnalyzer.ini 文件

3.1 指定jdk版本

比如我的是Eclipse Memory Analyzer Version 1.16.1

Eclipse Memory Analyzer (MAT) Version 1.16.1 对 JDK 版本的要求如下:

  • 最低支持 JDK 11:MAT 1.16.1 基于 Eclipse 平台构建,而该版本的 Eclipse 平台最低需要 JDK 11 才能运行。
  • 兼容更高版本 JDK:它可以在 JDK 11 及以上版本(如 JDK 17、JDK 21 等)中正常工作,支持当前主流的 LTS 版本。

例如,以下格式

-vm 
/Users/wyf/.sdkman/candidates/java/21.0.5-oracle/bin/java

3.2 指定内存大小

如果dump文件比较大,

需调整 MAT 启动参数:

  • 修改 MemoryAnalyzer.ini 文件中的 -Xmx 参数,例如 -Xmx8g 分配 8GB 内存

格式如下

-Xmx8g
-XX:+UseG1GC
-XX:MaxMetaspaceSize=1024m

如果dump文件比较大,

需调整 MAT 启动参数:

  • 修改 MemoryAnalyzer.ini 文件中的 -Xmx 参数,例如 -Xmx8g 分配 8GB 内存

二、加载堆 dump 文件

我这个堆dump文件大概2.3g左右

启动 MAT 后,通过菜单 File > Open Heap Dump 选择堆文件(如 .hprof 格式)。MAT 会自动解析文件并生成初始报告。首次加载时可能需较长时间,尤其是大文件。

打开之后的主页

三、分析内存泄漏

查看初始报告的 Leak Suspects 部分,MAT 会标记潜在内存泄漏点。例如:

  • 显示某个对象占用了 80% 的堆内存。
  • 点击 Details 查看具体对象引用链。

通过内存泄漏分析可以看到,我的项目的内存泄漏点是:“Class Name                                                                    | Shallow Heap | Retained Heap
-------------------------------------------------------------------------------------------------------------
org.hibernate.internal.util.collections.BoundedConcurrentHashMap @ 0x4e2c1c570|           48 | 2,016,348,896
-------------------------------------------------------------------------------------------------------------

手动分析 Dominator Tree:

  • 导航至 Dominator Tree 视图,按对象占用内存排序。
  • 右键选中高内存占用的对象,选择 Path to GC Roots > exclude weak/soft references,查看强引用路径。

可以看到大对象是:Class Name                                                                                   | Shallow Heap | Retained Heap | Percentage
-----------------------------------------------------------------------------------------------------------------------------------------
queryPlanCache org.hibernate.internal.util.collections.BoundedConcurrentHashMap @ 0x4e2c1c570|           48 | 2,016,348,896 |     91.71%
-----------------------------------------------------------------------------------------------------------------------------------------

gc之后依然占用2g左右

可以发现根源就是:Class Name                                                                | Shallow Heap | Retained Heap
---------------------------------------------------------------------------------------------------------
queryPlanCache org.hibernate.engine.query.spi.QueryPlanCache @ 0x4e2c1c550|           32 | 2,018,030,416
---------------------------------------------------------------------------------------------------------

四、检查对象直方图

Histogram 视图中,按类名统计对象数量和内存占用:

  • 输入类名过滤(如 String 或自定义类)。
  • 排序 Shallow HeapRetained Heap 定位异常对象。

五、常见问题排查

若 MAT 无法解析堆文件:

  • 检查堆文件完整性,尝试用 jhat 或 VisualVM 验证。
  • 确保 MAT 版本与 Java 版本兼容。

内存不足时:

  • 增加 MAT 的 -Xmx 参数,或分割堆文件后分次分析。

六、结论

具体原因:由 Hibernate SessionFactory 内部缓存导致,hibernateQueryPlanCache引发的heap区内存溢出

七、解决方案

查阅相关资料和类似问题,找出初步修改方案:

hibernate.query.plan_cache_max_size=128 ##根据项目实际修改

hibernate.query.plan_parameter_metadata_max_size=64 ##根据项目实际修改

hibernate.query.in_clause_parameter_padding=true ##in 查询参数过多会导致QueryCachePlan过快,5.3.0及更高版本的Hibernate有一个在IN子句中填充参数的的解决方案:复用执行计划。打开即可

通过JProfiler工具本地调试观察前后对比heap堆内存占用是否明显下降。(待验证)

通过以上步骤,可系统性地定位 和解决Java 应用的内存问题。


网站公告

今日签到

点亮在社区的每一天
去签到