jvm垃圾回收算法需结合收集器与内存区域理解:serial新生代用复制算法,serial old老年代用标记-整理,cms老年代用标记-清除以保低延迟但易碎片,g1通过region级标记-整理兼顾低延迟与无碎片。

Java 面试中问 JVM 垃圾回收算法,不是让你背诵“标记-清除”“复制”“标记-整理”的定义,而是看你能不能说清:每种算法在什么区域、什么条件下被实际使用,为什么 CMS 用标记-清除而 G1 用标记-整理,以及 CMS 的 Concurrent Mode Failure 和 G1 的 Evacuation Failure 分别卡在哪一步。
哪些 GC 算法对应哪些垃圾收集器
面试时混淆“算法”和“收集器”是高频失分点。算法是理论策略,收集器是具体实现——Serial、Parallel Scavenge、CMS、G1、ZGC 都是收集器,它们内部组合使用不同算法:
-
Serial(新生代):用 复制算法,因为 Eden/Survivor 空间小、对象朝生夕灭,复制比标记清除更高效 -
Serial Old(老年代):用 标记-整理,避免碎片化影响大对象分配 -
CMS(老年代):用 标记-清除,目标是低延迟,不整理所以停顿短;但会留碎片,触发Concurrent Mode Failure时退化为Serial Old -
G1:逻辑上分 Region,回收时对选中的 Region 使用 标记-整理(evacuation 阶段),既控制停顿又避免碎片
为什么 CMS 不用标记-整理?G1 又怎么兼顾低延迟和无碎片?
CMS 的设计前提是“并发清理”,而标记-整理必须移动对象、更新所有引用,这需要 Stop-The-World 且耗时不可控——直接违背其低延迟目标。所以它宁可忍受碎片,靠 initiatingOccupancyFraction 提前触发并发周期来规避。
G1 则把整理限制在部分 Region 内:每次只选回收价值高、存活对象少的 Region 进行 evacuation(即复制 + 整理),通过预测模型控制 STW 时间。它不用全堆整理,也不依赖内存连续,所以能同时满足停顿可控和长期运行不 OOM。
立即学习“Java免费学习笔记(深入)”;
关键区别:
- CMS 的
Concurrent Mode Failure发生在并发标记未完成、老年代就填满时,被迫启动 Full GC(Serial Old) - G1 的
Evacuation Failure发生在 Survivor 或 To Space 不足,无法完成对象复制时,会触发 Full GC 或扩容失败
年轻代 GC 为什么几乎都用复制算法?有没有例外?
复制算法适合年轻代,核心原因是:90%+ 对象在 Eden 区出生,一次 Minor GC 后约 95% 死亡,只需复制存活的 5%,效率远高于标记-清除或标记-整理。
但要注意两个边界情况:
-
Parallel Scavenge在 Survivor 空间不足时,会把部分对象直接晋升到老年代(HandlePromotionFailure),这不是算法切换,而是空间策略兜底 -
ZGC和Shenandoah不区分年轻代/老年代,全程用读屏障 + 并发转移,不依赖复制算法——这是现代 GC 的演进方向,面试提到能加分
面试时最容易被追问的细节
别只答“CMS 用标记-清除”,面试官大概率会立刻问:“那它怎么处理碎片?”或者“如果老年代碎片太多,CMS 会怎么做?”——这时候要立刻反应出:UseCMSCompactAtFullCollection(已废弃)、CMSScavengeBeforeRemark、以及最关键的:碎片积累后只能靠 Full GC 触发 Serial Old 的标记-整理来解决,但这恰恰是 CMS 最想避免的。
真正难的不是记住算法名字,而是理解每个选择背后的 trade-off:吞吐量 vs 延迟、内存占用 vs GC 频率、实现复杂度 vs 可预测性。JVM GC 没有银弹,只有约束下的权衡。










