必须配置-XX:+HeapDumpOnOutOfMemoryError和-XX:HeapDumpPath=/absolute/path/to/dumps/,确保路径为绝对路径、JVM运行用户有写权限、磁盘空间充足,否则dump将静默失败;推荐指定目录而非文件名以利用PID自动区分多次OOM,辅以GC日志提升分析价值。

Java应用发生内存溢出(OOM)时,关键不是等它崩溃,而是让JVM在抛出OutOfMemoryError的瞬间自动生成堆转储(heap dump),为后续分析泄漏源头留下完整现场。配置本身不难,但生产环境常因路径、权限、覆盖逻辑等细节导致dump静默失败——这恰恰是排查被卡住的主因。
必须加的两个JVM参数
仅启用开关而不指定路径,等于没配:
- -XX:+HeapDumpOnOutOfMemoryError:开启OOM自动dump功能,这是触发动作的开关
-
-XX:HeapDumpPath=/absolute/path/to/dumps/:必须用绝对路径,指向一个JVM运行用户(如
appuser)有写权限、且磁盘空间充足的目录
错误示例:-XX:HeapDumpPath=~/dumps(~不展开)、-XX:HeapDumpPath=./dumps(相对路径)、-XX:HeapDumpPath=/tmp(/tmp可能只读或空间不足)。
路径权限与容器部署要点
dump失败从不报错,只会静默跳过。常见原因和应对方式:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 确认目标目录归属和权限:
chown appuser:appuser /var/log/myapp/heapdumps && chmod 755 /var/log/myapp/heapdumps - Docker中需挂载宿主机目录,并确保容器内UID与宿主机目录所有者匹配,否则即使路径存在也会被拒绝写入
- 不要把dump路径设为日志目录或应用根目录——这些位置往往权限受限或空间紧张
生成文件名与多次OOM区分
JVM原生不支持时间戳或自定义命名,但已有天然区分机制:
- 若
-XX:HeapDumpPath指定为目录(如/dumps/),每次OOM会生成形如java_pid12345.hprof的文件,PID已保证唯一 - 若指定为完整文件名(如
/dumps/oom.hprof),第二次OOM会因文件已存在而失败 - 如需带时间标记,应在dump生成后由外部脚本处理,例如监听目录变化后重命名为
heap_$(date +%Y%m%d_%H%M%S)_12345.hprof
辅助参数提升分析价值
单靠dump不够,配合GC日志才能判断是真泄漏还是配置过小:
- 加上
-Xloggc:/var/log/myapp/gc.log -XX:+PrintGCDetails,OOM前的GC行为一目了然 - 慎用
-XX:+UseGCOverheadLimit:它可能在真正堆溢出前就终止进程,导致HeapDumpOnOutOfMemoryError不触发 - 调试期可临时加
-XX:+HeapDumpBeforeFullGC,获取Full GC前快照用于对比,但生产环境避免开启——它会显著拖慢GC过程

















