跳转到主内容
极星编程网:以代码为星,赴技术山海!

Java面试——JVM垃圾回收算法详解

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免费学习笔记(深入) ”; 关键区别: Eclipse导入Android或其他的JAVA项目的正确方法 WORD版 本文档主要讲述的是Eclipse导入Android或其他的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 没有银弹,只有约束下的权衡。

相关文章