G1收集器将堆划分为最多2048个大小为1~32MB的Region,每个Region动态承担Eden、Survivor、Old或Humongous角色;通过Remembered Set避免全堆扫描,Mixed GC按垃圾密度增量回收Old Region,结合复制算法与预留机制最大限度避免Full GC。

G1 收集器不按传统方式划分连续的年轻代和老年代,而是把堆切成多个大小相等、物理上不连续的 Region,每个 Region 动态承担 Eden、Survivor、Old 或 Humongous 角色,回收时只挑“垃圾最多”的区域下手,既控停顿又保吞吐。
Region 的划分规则与角色动态性
堆被划分为最多 2048 个 Region,大小在 1MB~32MB 之间,取值为 2 的幂(如 1、2、4、8…32MB),默认由 JVM 根据堆总大小自动计算:堆大小 ÷ 2048,再向上取整到最近的 2 的幂。例如 4GB 堆 → 约 2MB/Region。
- 每个 Region 在运行时仅有一种逻辑角色:Eden、Survivor、Old 或 Humongous,但可随 GC 动态切换(如 Survivor 区对象晋升后,该 Region 可转为 Old)
- Humongous Region 专用于 ≥ 当前 Region 50% 大小的对象(如 Region 为 2MB,则 ≥1MB 的对象即算巨型);超大对象会占用连续多个 Humongous Region
- 空闲 Region(Free)随时可被分配为任意角色,无固定归属
局部变量扫描如何避开全堆遍历
局部变量本身在 Java 栈上,不占堆空间,但它引用的对象在堆中。G1 不扫描所有线程栈帧,而是靠 Remembered Set(RSet)精准定位跨 Region 引用。
- RSet 存储“谁指向我”——即其他 Region 中哪些卡(Card,512 字节)里有指向本 Region 的引用
- 写屏障(Write Barrier)在对象引用赋值时异步更新 RSet,开销可控
- Young GC 时,只需扫描 Eden/Survivor Region + 对应 RSet 中标记的跨区引用,完全跳过未被引用的老年代 Region
Mixed GC 的触发逻辑与增量回收机制
Mixed GC 是 G1 实现低停顿的核心,它不是一次性清理所有老年代,而是每次选一部分“高垃圾密度”的 Old Region 加入回收集合(CSet),与 Young GC 同步执行。
- 触发条件:并发标记周期完成,且满足 -XX:G1MixedGCCountTarget(默认 8 次)和 -XX:G1OldCSetRegionThresholdPercent(默认 10%,即老年代中至少 10% Region 达到可回收阈值)
- CSet 按“回收收益 / 时间比”排序,优先选垃圾占比高、复制耗时低的 Region
- 每次 Mixed GC 回收的 Old Region 数量受 -XX:MaxGCPauseMillis 控制,G1 基于历史回收数据预测耗时,动态调整 CSet 大小
避免 Full GC 的关键设计保障
G1 的目标是彻底摆脱 Full GC,主要依靠三方面设计:
- Humongous Region 虽属老年代语义,但其回收依赖 Mixed GC 或并发标记后的专门清理,不等待 Full GC
- Region 复制算法天然整理内存,消除碎片,避免因空间不连续导致的大对象分配失败
- 当 Humongous 分配失败(找不到足够连续 Region)或并发标记严重滞后时,仍可能退化为 Full GC,因此需监控 -XX:G1HeapRegionSize 和 -XX:G1ReservePercent(预留空闲 Region 防止分配失败)

















