g1与cms的本质区别在于内存组织方式和垃圾回收策略:cms采用固定分代模型,仅回收老年代,依赖标记-清除算法,易产生碎片;g1采用region动态分区模型,全域回收,基于标记-整理算法,实现可预测停顿与无碎片整理。

G1 和 CMS 的本质区别,核心就落在“怎么组织内存”和“怎么收拾垃圾”这两件事上。
内存不是固定分块,而是动态划区
CMS 依赖物理分代:堆被硬性切成新生代(Eden + Survivor)和老年代,角色固定、边界清晰。新生代用复制算法,老年代只能靠 CMS 自己处理,必须搭配 ParNew 等新生代收集器才能跑起来。
G1 打破这种刚性结构:整个堆被均分为多个大小相等的 Region(通常 1–32MB),每个 Region 可随时扮演 Eden、Survivor、Old,甚至 Humongous(超大对象专用)。新生代和老年代只是逻辑概念——它们是不同 Region 的动态集合,不连续、不固定。
- Region 之间通过 Remembered Set 记录跨区引用,避免全堆扫描
- Young GC 只清理 Eden 和 Survivor Region;Mixed GC 则按收益高低,挑出部分老年代 Region 一起回收
- 无需额外搭配其他收集器,G1 是独立闭环的全域收集器
回收后要不要“归位”,决定了碎片命运
CMS 用标记-清除算法:只把死亡对象标记出来再清掉,存活对象原地不动。结果就是老年代里空洞散落,碎片越积越多。一旦需要分配大对象,即使总空间充足,也可能因找不到连续内存而触发 Full GC。
G1 默认采用标记-整理策略:回收完成后,会把存活对象向 Region 一端压缩,腾出整块连续空闲空间。它不是等碎片严重了再“补救”,而是在每次 Young GC 和 Mixed GC 中就同步完成局部整理。
- CMS 的碎片整理需显式开启参数(-XX:+UseCMSCompactAtFullCollection),且只能在 STW 的 Full GC 阶段执行
- G1 的整理是增量式的、伴随回收发生的,几乎不额外增加停顿
- 因此 G1 基本不会因碎片导致意外 Full GC,CMS 却常因此“雪崩”
停顿时间能不能控住,关键看回收节奏
CMS 的目标是“最短单次停顿”,但它无法保证每次停顿都稳定——并发失败、浮动垃圾堆积、碎片引发的 Full GC,都可能突然拉长 STW 时间,有时达数秒。
G1 的设计哲学是“可预测停顿”:通过 -XX:MaxGCPauseMillis 设定目标(如 200ms),JVM 会动态估算哪些 Region 回收性价比最高、耗时最可控,并在一次 GC 中只处理这些 Region。混合回收把老年代压力拆解到多次 GC 中,避免集中爆发。
- CMS 的 STW 发生在初始标记和重新标记两个阶段,后者容易受应用负载波动影响
- G1 的 STW 主要在初始标记和最终标记,其中初始标记常复用 Young GC 的暂停,开销更小
- G1 的筛选回收(Evacuation)阶段虽需移动对象,但因 Region 小、范围可控,停顿更平稳
区域化布局带来灵活调度,压缩能力保障长期稳定——这不是功能叠加,而是底层设计范式的切换。











