垃圾回收器有哪些?CMS 和 G1 的区别?

2025年 阅读约 10 分钟 面试指南 · Java面试 · JVM

深入解析JVM七大垃圾回收器:Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS、G1、ZGC,重点对比CMS和G1的原理、优缺点和适用场景,附完整面试模拟。

一句话总结

JVM 垃圾回收器按分代可分为:新生代(Serial、ParNew、Parallel Scavenge)、老年代(Serial Old、Parallel Old、CMS)、整堆(G1、ZGC、Shenandoah)。CMS(JDK 5-8)以最短 STW 为目标,使用标记-清除算法,有碎片和浮动垃圾问题。G1(JDK 9+ 默认)将堆划分为 Region,优先回收垃圾最多的 Region,可预测停顿时间。ZGC(JDK 11+)目标是将 STW 控制在 10ms 以内。

初级理解

七大垃圾回收器一览

收集器作用区域算法线程特点
Serial新生代复制单线程简单高效,适合客户端
ParNew新生代复制多线程Serial 的多线程版,配合 CMS
Parallel Scavenge新生代复制多线程关注吞吐量,自适应调节
Serial Old老年代标记-整理单线程客户端模式备用
Parallel Old老年代标记-整理多线程配合 Parallel Scavenge
CMS老年代标记-清除多线程低停顿,JDK 14 移除
G1整堆标记-整理+复制多线程可预测停顿,JDK 9 默认

经典组合

// JDK 8 及以前常用组合 -XX:+UseSerialGC // Serial + Serial Old(客户端) -XX:+UseParallelGC // Parallel Scavenge + Serial Old -XX:+UseParallelOldGC // Parallel Scavenge + Parallel Old(吞吐量优先) -XX:+UseConcMarkSweepGC // ParNew + CMS + Serial Old 备用(低延迟) -XX:+UseG1GC // G1(JDK 9+ 默认)

中级深入

CMS 工作流程

// CMS(Concurrent Mark Sweep)四个阶段: // ① 初始标记(STW):标记 GC Roots 直接关联的对象,很快 // ② 并发标记:从 GC Roots 遍历对象图,与用户线程并发 // ③ 重新标记(STW):修正并发标记期间变动的标记,比初始标记稍长 // ④ 并发清除:清除未标记对象,与用户线程并发 // CMS 三大问题: // 1. 并发标记占用 CPU,降低吞吐量 // 2. 并发清除产生浮动垃圾,可能触发 Concurrent Mode Failure → Serial Old // 3. 标记-清除产生内存碎片 → 可能触发 Full GC

G1 工作流程

// G1(Garbage First)将堆划分为大小相等的 Region(1~32MB) // 每个 Region 可以是 Eden、Survivor、Old、Humongous // G1 的 GC 周期: // ① 初始标记(STW):标记 GC Roots,借用 Minor GC 完成 // ② 并发标记:遍历对象图,与用户线程并发 // ③ 最终标记(STW):处理 SATB 缓冲区中的引用变更 // ④ 筛选回收(STW):对各个 Region 的回收价值和成本排序, // 优先回收垃圾最多的 Region(Garbage First 名字由来) // G1 核心优势: // - 可预测停顿:-XX:MaxGCPauseMillis=200(默认 200ms) // - 无碎片:使用标记-整理 + 复制算法 // - 增量回收:每次只回收部分 Region

高级拓展

CMS vs G1 深度对比

特性CMSG1
内存布局连续的新生代+老年代划分为多个 Region
回收算法标记-清除(有碎片)标记-整理+复制(无碎片)
停顿预测不可预测可设置停顿目标
大对象直接进入老年代Humongous Region(多个连续 Region)
记忆集卡表卡表 + 哈希表(更占内存)
适用堆< 6GB6GB ~ 几十 GB
JDK 状态JDK 14 移除JDK 9+ 默认

ZGC 和 Shenandoah

// ZGC(JDK 11 引入,JDK 15 生产可用) // 目标:STW < 10ms,支持 TB 级堆 // 核心技术:染色指针(Colored Pointers)+ 读屏障 // 并发执行几乎所有阶段,包括并发整理 // Shenandoah(JDK 12 引入) // 目标:低停顿,与堆大小无关 // 核心技术:Brooks Pointer + 转发指针 // 并发整理:将对象复制到新位置,同时更新引用

实战场景

如何选择垃圾回收器?

场景推荐理由
客户端小应用Serial单线程,内存小,简单高效
后台计算任务Parallel吞吐量优先,CPU 利用率高
Web 应用(JDK 8)CMS / G1低延迟,减少用户感知停顿
大堆(> 6GB)G1可预测停顿,无碎片
超大堆(> 几十 GB)ZGC亚毫秒级停顿

面试模拟

Q:CMS 和 G1 的区别?

A:1) 内存布局:CMS 是连续分代,G1 是 Region 化;2) 算法:CMS 标记-清除有碎片,G1 标记-整理+复制无碎片;3) 停顿:CMS 不可预测,G1 可设置停顿目标;4) 大对象:CMS 直接进老年代,G1 用 Humongous Region;5) 适用:CMS 适合 6GB 以下,G1 适合 6GB 以上;6) 状态:CMS 在 JDK 14 已移除。

Q:G1 的 Region 是什么?为什么叫 Garbage First?

A:G1 将堆划分为大小相等的 Region(1~32MB),每个 Region 可以是 Eden、Survivor、Old 或 Humongous。回收时对各个 Region 的回收价值(垃圾量)和成本(时间)排序,优先回收垃圾最多的 Region,所以叫 Garbage First。这样可以在有限停顿时间内回收尽可能多的垃圾。

Q:CMS 的 Concurrent Mode Failure 是什么?

A:CMS 并发清除时,用户线程仍在产生垃圾(浮动垃圾)。如果老年代剩余空间不足以容纳浮动垃圾,就会触发 Concurrent Mode Failure,JVM 会退化为 Serial Old 进行 Full GC,导致长时间 STW。解决:预留足够的老年代空间(-XX:CMSInitiatingOccupancyFraction 调低),或增大堆内存。