Promotion Failed 根本原因是老年代缺乏足够连续空闲空间,而非总量不足;CMS等无压缩能力回收器因标记-清除算法产生碎片,大对象无法拆分分配,导致即使总剩余空间充足仍晋升失败,并触发Full GC或Concurrent Mode Failure。

Promotion Failed 表示年轻代对象在 Minor GC 后无法成功晋升到老年代,根本原因不是老年代完全没空间,而是缺乏足够大的连续空闲内存块来容纳这批待晋升对象。
这通常发生在 CMS 或 Parallel Old 等不带压缩能力的回收器上。CMS 用“标记-清除”算法,清理后容易留下大量碎片;当一个几百 KB 甚至几 MB 的大对象(如大数组、长字符串、缓存块)需要晋升时,它必须整块分配,无法拆分——哪怕老年代总剩余空间有 2GB,只要最大连续空闲块只有 300KB,就会触发 Promotion Failed。
日志里最典型的信号是:
-
[ParNew (promotion failed): 146112K->146112K(153600K), 0.2255230 secs]
年轻代使用量几乎没变,说明 GC 没回收出空间,对象全卡在 Eden/Survivor,等着进老年代却进不去; - 紧接着出现
[Full GC ...]
JVM 启动兜底机制,退化为 Stop-The-World 的串行或并行 Full GC,耗时显著拉长; - 若用 CMS,常伴随
CMS-concurrent-mark (concurrent mode failure)
因晋升失败导致老年代瞬间失守,CMS 还没完成并发标记就被迫中止,转而执行代价更高的 Full GC。
它不是单纯的“内存不够”,而是“内存够但拼不出一块整地”——本质是老年代碎片化 + 大对象集中晋升共同作用的结果。

















