java堆溢出排查三步法:先确认错误类型(java heap space才是真堆溢出),再通过jvm参数自动或手动获取堆转储文件,最后用mat分析leak suspects、histogram和dominator tree定位内存泄漏源头。

看到 java.lang.OutOfMemoryError: Java heap space,别急着调大堆内存。真正有效的排查,是快速锁定“到底是对象太多、还是根本回收不掉”。核心就三步:确认类型、捕获现场、定位源头。
第一步:看错信息,10秒内锁定是不是真堆溢出
错误日志里只认准这一行:
- Java heap space → 真堆溢出,继续往下查
- Metaspace → 类加载问题,不是堆的事
- Direct buffer memory → NIO 直接内存,跟 -Xmx 无关
- GC overhead limit exceeded → 堆其实够用,但 GC 已经干不动了,大概率有大对象或泄漏
顺手用 jps -l 找进程 ID,再用 jinfo -flags
第二步:让 JVM 自动留证据,别等下次
立刻加两个 JVM 参数重启(生产环境建议灰度):
- -XX:+HeapDumpOnOutOfMemoryError:OOM 时自动生成 .hprof 文件
- -XX:HeapDumpPath=/path/to/dumps/:指定保存路径,确保磁盘有空间且可写
如果服务已卡死但还没 OOM,可用 jmap -dump:format=b,file=/path/dump.hprof
第三步:用 MAT 快速揪出“内存大户”
打开 .hprof 文件后,按顺序点这三项:
- Leak Suspects Report:MAT 自动生成的嫌疑报告,通常第一项就是主因,直接点进去看引用链
- Histogram:按类统计实例数和内存占比,找 “Retained Heap” 最大的几个类
- Dominator Tree:看谁真正“霸占”内存,展开后右键 → Path to GC Roots → exclude weak/soft references,找到强引用链终点
常见高危模式:静态 Map/List 不断 add、ThreadLocal 没 remove、缓存没设上限、流式处理没 close、日志打印了整张大对象。











