oom发生时应优先保障可观测性:启用-xx:+heapdumponoutofmemoryerror自动导出堆快照,配合-xx:heapdumppath指定绝对路径;可用-xx:onoutofmemoryerror执行轻量告警脚本,结合prometheus+jmx实现内存使用率超85%预警。

发生OOM时,不应急着“救活”JVM,而要优先确保可观测性与快速响应——核心是让系统在崩溃前留下线索,并通知相关人员。
启用自动堆转储与路径规范
这是最基础也最关键的一步。JVM在抛出java.lang.OutOfMemoryError: Java heap space前,可自动生成堆快照(heap dump),用于后续分析泄漏根源。
- 启动时添加参数:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/app/dumps/ - 路径必须存在且Java进程有写权限;建议用绝对路径,避免因工作目录变动导致dump失败
- 可加
-XX:HeapDumpBeforeFullGC(JDK 17+)提前捕获Full GC前的内存状态,辅助判断是否已濒临临界
用-XX:OnOutOfMemoryError触发轻量级动作
该参数允许在OOM发生瞬间执行一个外部命令,适合做即时告警或诊断采集,但不可依赖其“修复”问题。
- 示例:发送邮件 + 保存线程快照
-XX:OnOutOfMemoryError="sh /opt/app/bin/oom-handler.sh %p"
其中%p会被替换为当前Java进程PID -
oom-handler.sh中应尽量短小:调用mail发通知、执行jstack -l %p > /tmp/oom_jstack_%p_$(date -I).log、记录时间戳即可 - 避免在脚本中执行耗时操作(如压缩dump、远程上传),因JVM此时可能已卡顿或即将退出
结合JVMTI实现更早干预(进阶)
若需在内存真正耗尽前预警(例如元空间接近上限、直接内存持续增长),可基于JVMTI编写代理,在ResourceExhausted事件回调中触发逻辑。
- 适用于高稳定性要求场景,如金融交易中间件
- 需自行编译C++ agent并加载:
-agentpath:/path/to/liboomwatcher.so - 可在内存使用达阈值(如Metaspace使用率>90%)时主动记录日志、降级非核心功能,而非坐等OOM
配套监控与基线建设
单靠OOM事件响应是被动的。真正优雅的响应,建立在日常可观测性之上:
- 用Prometheus + JMX Exporter采集
java_lang_Memory_Pool_Usage_used等指标,设置堆/元空间使用率>85%的预警 - 定期跑
jstat -gc <pid> 5s</pid>观察GC频率与老年代增长趋势,比等OOM更早发现问题 - 将典型OOM场景(如静态Map无限增长、DirectByteBuffer未清理)纳入CI阶段的内存压力测试用例
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











