必须配齐-XX:+HeapDumpOnOutOfMemoryError、-XX:HeapDumpPath(绝对路径且权限正确)、GC日志参数,否则dump可能无法生成或无效;还需验证路径可写、磁盘充足,并用测试触发确认.hprof文件成功生成且格式有效。

要让 JVM 在发生 OutOfMemoryError(OOM)时自动保存堆快照,光加一个 -XX:+HeapDumpOnOutOfMemoryError 是不够的。关键在于确保 dump 能真正写出来、写对地方、写得有用。
必须配齐的三个核心参数
单独启用 -XX:+HeapDumpOnOutOfMemoryError 只是打开开关,实际能否生成文件,取决于配套配置:
-
-XX:HeapDumpPath=/data/dumps/:指定绝对路径,不能用
~/dumps或相对路径;目录需提前创建,且 Java 进程用户(如tomcat或appuser)对该路径有写权限 - -XX:+PrintGCDetails -Xlog:gc*:file=/var/log/myapp/gc.log(JDK 9+)或 -verbose:gc -Xloggc:/var/log/myapp/gc.log(JDK 8):开启详细 GC 日志,与 dump 时间对齐后可还原 OOM 前内存变化趋势
- -XX:+HeapDumpBeforeFullGC(可选但推荐):在每次 Full GC 前也存一份 dump,有助于发现渐进式内存泄漏,不依赖 OOM 触发
路径与权限的实操要点
很多团队配置了参数却没生成 .hprof 文件,问题几乎都出在路径上:
- Kubernetes 环境中避免用
/tmp,它通常是 tmpfs,空间小且重启即丢;应挂载持久卷到明确路径,例如/data/dumps - 检查权限:运行
ps -o user= -p $(pgrep -f MyApplication)查看 Java 进程用户,再执行ls -ld /data/dumps确认该用户有写权限 - 路径末尾不带
.hprof更安全(如/data/dumps/),JVM 会自动生成java_pid12345.hprof;若带后缀(如/data/dumps/oom.hprof),多次 OOM 会覆盖同一文件 - JVM 不会自动创建父目录,
mkdir -p /data/dumps && chown appuser:appuser /data/dumps必须提前执行
应对大堆与磁盘压力的策略
堆设为 4GB+ 时,dump 文件可能超 10GB,需提前规划:
- 使用 G1 垃圾回收器并调优:
-XX:+UseG1GC -XX:G1HeapRegionSize=2M(根据堆大小调整),提升回收效率,间接减小 dump 体积 - 64 位 JVM 默认开启
-XX:+UseCompressedOops,减少对象指针开销,压缩 dump 尺寸 - 用脚本定期清理旧文件:例如
find /data/dumps -name "*.hprof" -mtime +7 -delete - 监控磁盘水位:OOM 常发生在磁盘已近满时,
df -h /data应纳入告警项
上线前必须做的验证动作
别等真出故障才确认配置是否生效:
- 写个测试接口,循环分配大数组(如
new byte[100 * 1024 * 1024]),快速触发 OOM - 观察日志是否输出
java.lang.OutOfMemoryError: Java heap space - 立刻检查
/data/dumps/是否生成.hprof文件,并用file java_pid*.hprof验证格式(应显示 “Java Heap Dump”) - 用
jhat或 MAT 打开文件,确认能正常加载对象统计视图










