oom前兆是eden区gc后残留高、survivor区持续淤积、old区单边爬升且回收微弱,三区联动恶化预示崩溃倒计时。

看懂 GC 日志中 Eden、Survivor、Old 区在 OOM 前夕的异常模式,关键不是等报错才翻日志,而是提前识别“呼吸变浅”的信号——比如 Eden 频繁满但回收后空间不释放、Survivor 区持续淤积、Old 区使用量单边爬升且回收效果微弱。
Eden 区:高频分配 + 低效回收 = 即将溢出
正常情况:Eden 满触发 Young GC,回收后使用量归零或极低(如 [Eden: 128M->0B(128M)])。
OOM 前兆表现:
- Eden 区每次 GC 后仍残留大量内存(如
[Eden: 128M->95M(128M)]),说明对象存活率高,年轻代压力过大; - Young GC 频率陡增(例如从每 5 秒一次变成每 200ms 一次),但 Eden 回收量几乎不变,反映新对象“生得快、死不了”;
- 伴随
Allocation Failure频繁出现,且 GC 耗时未显著下降,说明分配速率已逼近吞吐极限。
Survivor 区:空间滞胀 + 年龄堆积 = 晋升失衡
Survivor 的设计本意是缓冲和筛选,理想状态是利用率长期低于 50%,且两区总有一块为空。
危险信号包括:
- Survivor 使用率持续 >70%(如
[Survivor: 10M->9.8M(10M)]),甚至反复接近满载,说明对象在年轻代“卡关”; - 同一对象在 Survivor 中多次复制却未晋升,或大批对象年龄集中卡在阈值前(如大量 age=14),暗示
-XX:MaxTenuringThreshold设置不合理或对象生命周期被意外拉长; - GC 日志中出现
Desired survivor size远大于实际可用空间,JVM 被迫提前晋升,加剧老年代压力。
Old 区:缓慢上涨 + 回收无力 = 崩溃倒计时
老年代增长本应平缓,Major GC 或 Mixed GC 应能有效回落其水位。
OOM 前典型特征:
- Old 区使用量持续单向攀升,且每次 GC 后仅下降极小比例(如
[Tenured: 65536K->65200K(131072K)],只回收 336K); - Full GC 或 Mixed GC 频次增加,但耗时变长、回收量变少,甚至出现
concurrent mode failure或promotion failed; - Old 区占用长期超过堆上限的 75%,尤其在 G1 中观察
old: 240持续高位而free: 1520 → 1400 → 1200逐轮递减,Free Region 快速枯竭。
联动指标:三区协同恶化才是真警报
单独某区异常可能只是局部问题,但多个区域同步恶化,就是 OOM 的明确前奏:
- Young GC 后 Eden 清空,但 Old 区立刻暴涨(
98304K→72000K中 Old 贡献了大部分),说明大量对象“秒晋老年代”; - Survivor 区未满,却频繁发生
promotion failed,通常因大对象直接分配失败或 Humongous 分配触发 Full GC; - Metaspace 稳定但 Old 区飙高,基本可排除类加载泄漏,聚焦业务对象生命周期管理(如缓存未清理、监听器未注销、流未关闭)。










