一、安装与配置 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 Heap
或Retained 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 应用的内存问题。