-xx:onoutofmemoryerror用于oom时执行指定shell命令,需配合-xx:+heapdumponoutofmemoryerror使用,支持%p占位符,要求绝对路径、权限正确及前台启动;其本质是事后响应,须结合堆转储分析、systemd自动重启与监控形成闭环,不可替代根因治理。

-XX:OnOutOfMemoryError 是 JVM 提供的一个关键参数,它允许你在 JVM 发生 OutOfMemoryError 时,自动触发一条 shell 命令——比如发送告警、保存诊断信息,甚至尝试重启服务。但它不是“万能重启开关”,用不好反而掩盖问题、干扰故障定位。
一、基础配置写法与生效前提
该参数必须配合 -XX:+HeapDumpOnOutOfMemoryError(推荐同时启用)使用,典型写法如下:
-XX:OnOutOfMemoryError="sh /opt/app/scripts/oom-handler.sh %p"-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/app/heap-dump.hprof
注意:
• %p 是占位符,会被替换成当前 JVM 进程 PID,方便脚本精准操作;
• 命令路径必须是绝对路径,且 JVM 启动用户需对脚本及目标目录有执行/写入权限;
• JVM 必须以 前台方式启动(如 systemd service 中设 Type=simple),否则信号可能无法正确传递。
二、推荐的 oom-handler.sh 脚本内容
不建议直接在参数里写复杂命令,应封装为可维护脚本。一个实用示例:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 记录时间、PID、主机名到日志;
- 调用
jstack %p > /var/log/app/jstack-$(date +%s).log抓取线程快照; - 用
systemctl restart app-order-service触发 systemd 重启(前提是已配置好自动重启策略); - 通过
curl或echo向企业微信/钉钉机器人发简短告警(含服务名和时间); - 最后
exit 1确保 JVM 进程真正退出(避免残留状态)。
三、为什么不能只靠它“自动恢复”?
这个参数本质是“事后响应”,而非“根因解决”。常见误区包括:
- 把它当重启替代方案:若未配 systemd 的
Restart=on-failure,JVM 退出后进程就没了,服务仍不可用; - 忽略堆转储分析:每次 OOM 都应保留
.hprof文件,用 Eclipse MAT 或 JProfiler 查泄漏源头; - 脚本中执行
kill -9 %p多余且危险:JVM 已在抛异常后准备退出,再 kill 可能中断 dump 写入; - 没做资源隔离:容器环境下未加
-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0,会导致反复 OOM。
四、配合 systemd 才算真正闭环
单独用 -XX:OnOutOfMemoryError 只是半截逻辑。完整防护链应是:
- JVM 检测到 OOM → 执行脚本 → 保存现场 + 发告警;
- 进程退出 → systemd 捕获 exit code 143(或任意非零)→ 根据
Restart=on-failure自动拉起新进程; - 新进程启动时,加载优化后的 JVM 参数(如合理堆上限、GC 日志)、并接入 Prometheus 监控堆使用率。
这样既保留了人工介入窗口,又避免服务长时间离线。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










