要定位占堆内存90%的对象,关键是识别高占比、可回收却未回收的主导对象及其持有关系;通过Histogram找量大持续涨的业务类,Dominator Tree锁定内存大户,Path to GC Roots追查强引用链,结合jmap -histo:live交叉验证,聚焦前1–3个高Retained Heap业务类即可。

要定位哪些对象占用了堆内存的 90%,关键不是“凑够90%”,而是精准识别高占比、可回收却未被回收的主导对象及其持有关系。实际分析中,往往前几个类或对象就合计占了绝大部分(比如70%–95%),找到它们就等于锁定了问题主因。
直接看 Histogram:找“量大+持续涨”的业务类
打开 MAT 加载堆转储后,首先进 Histogram 视图:
- 点击列头 Objects 降序排列,重点关注你自己的包(如
com.example.*)下的类 - 忽略
java.lang.String、byte[]、char[]等基础类型——它们是结果,不是根因 - 如果
OrderCache实例数达 120 万,而线上正常应≤5000,这就是强信号 - 同时看 Retained Heap 列:若某类 Retained Heap 占总堆的 65%,它大概率就是“90% 占用”的核心组成部分
用 Dominator Tree 锁定“内存大户”
切换到 Dominator Tree,按 Retained Heap 降序:
- 排名第一的对象通常是一个静态容器(如
static ConcurrentHashMap)、线程池(ThreadPoolExecutor)、或全局缓存实例 - 展开它,能看到它直接/间接支配的所有对象,加起来往往就覆盖了堆的大部分
- 若看到
org.apache.catalina.loader.WebappClassLoader占比异常高,可能涉及类加载器泄漏
沿 Path to GC Roots 追查“为什么没被回收”
在 Histogram 或 Dominator Tree 中选中可疑对象 → 右键 → Path to GC Roots → exclude all except strong refs:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
立即学习“Java免费学习笔记(深入)”;
- 路径终点如果是
java.lang.Thread,说明被某个长期运行线程持有(如未 shutdown 的定时任务) - 终点是
static final字段或static HashMap,基本确认是静态引用导致无法释放 - 出现
ThreadLocalMap→ThreadLocal→ 你的业务类,提示 ThreadLocal 未调用remove()
辅助验证:用 jmap -histo:live 快速交叉比对
不等 MAT 加载完,先执行:
jmap -histo:live <pid> | head -n 30
- 对比输出中
#instances和#bytes都靠前的自定义类,是否与 MAT 中的高 Retained Heap 类一致 - 若
UserSession实例数 89 万、字节数 1.2GB,而总堆约 1.5GB,它单独就占了 80%+,无需再猜
定位目标不是精确算出“90%”,而是快速聚焦到那个真正拖垮堆的少数对象。只要把前 1–3 个高 Retained Heap 的业务类及其强引用链搞清楚,90% 的内存占用结构就自然浮现了。

















