Skip to content

G1 概述/优势/适用场景

G1:重新定义垃圾回收

G1(Garbage-First) 是 JDK 7 引入、JDK 9 成为默认的垃圾回收器。它不是简单地把堆分成年轻代和老年代,而是把整个堆划分为多个大小相等的 Region,通过优先回收价值最高的 Region,实现可预测停顿时间

G1 的核心设计

Region 划分

G1 把整个堆划分成多个大小相等的 Region(每个 1MB~32MB):

G1 堆结构:
┌──────────┬──────────┬──────────┬──────────┐
│   Eden  │   Eden   │  Survivor│   Old   │
│  Region  │  Region  │  Region  │  Region  │
├──────────┼──────────┼──────────┼──────────┤
│   Old    │   Old    │Humongous │   Free   │
│  Region  │  Region  │  Region  │  Region  │
├──────────┴──────────┴──────────┴──────────┤
│               G1HeapRegionSize                     │
│         (可配置:1MB, 2MB, 4MB, 8MB...)      │
└─────────────────────────────────────────────┘

G1 的 Region 类型

Region 类型说明
Eden Region年轻代,存储新分配的对象
Survivor Region年轻代,存储经历过 MinorGC 的存活对象
Old Region老年代,存储长期存活的对象
Humongous Region存储大对象(超过 Region 大小 50%)
Free Region空闲区域,可分配

G1 的分代 vs 传统分代

传统分代(Serial/Throughput/CMS):
┌──────────────────┐  ┌──────────────────┐
│      年轻代        │  │      老年代        │
│  Eden │ S0 │ S1 │  │                   │
│  (连续区域)        │  │   (连续区域)      │
└──────────────────┘  └──────────────────┘

G1 分代:
┌────────┬──────┬──────┬────────┬────────┐
│  Eden  │  S0  │  S0  │  Old   │  Old   │
│ (Region)│(Reg) │(Reg) │(Reg)  │(Reg)  │
├────────┴──────┴──────┴────────┴────────┤
│              堆被划分为多个 Region              │
│              各类型 Region 不必连续              │
└─────────────────────────────────────────────┘

G1 的工作过程

年轻代收集(Young GC)

G1 年轻代收集:

1. 分配新对象到 Eden Region

2. Eden Region 满

3. 选定所有 Eden Region 作为收集集合(CSet)

4. 多线程并行复制到 Survivor Region

5. 存活对象年龄达标 → 晋升到 Old Region

混合收集(Mixed GC)

当老年代 Region 达到阈值时,G1 执行混合收集:

G1 混合收集:

1. 选定所有年轻代 Region + 若干老年代 Region

2. CSet(收集集合)中所有存活对象被复制/清除

3. 存活对象复制到 Survivor/Old Region

4. 被清空的 Region 变成 Free Region

G1 的核心优势

1. 可预测停顿时间

G1 可以设置目标停顿时间

bash
# 设置目标最大停顿时间 200ms
java -XX:MaxGCPauseMillis=200 -XX:+UseG1GC MyApp

G1 会尽量满足这个目标——优先收集垃圾最多的 Region。

2. 空间整合

G1 不像 CMS 那样产生碎片。每次收集后,被清空的 Region 变成 Free Region,可以立即分配新对象:

G1 收集后:
┌────────┬────────┬────────┬────────┬────────┐
│  Free  │  Free  │  Old   │  Free  │  Eden  │
│ (Reg)  │ (Reg)  │ (Reg)  │ (Reg)  │ (Reg)  │
└────────┴────────┴────────┴────────┴────────┘
  ↓ 新对象可以直接分配到 Free Region

3. 停顿时间预测

G1 通过 Remembered Set 追踪 Region 间的引用,可以精确预测每个 Region 的回收价值:

回收价值计算:
  价值 = (可回收内存量) / (回收所需时间)

G1 优先收集价值最高的 Region:
  - 垃圾多的 Region → 回收空间大 → 价值高
  - 回收快的 Region → 所需时间少 → 价值高

4. 不需要连续空间

G1 的 Region 不需要物理连续——这解决了 CMS 和 Serial Old 的碎片问题。

G1 vs 其他收集器

维度SerialParallelCMSG1
停顿时间很长可预测
吞吐量
内存碎片有碎片无碎片
大堆支持一般一般
可预测性
JDK 默认---JDK 9+

G1 的适用场景

场景推荐原因
JDK 9+ 新项目默认 GC,开箱即用
追求低延迟可设置目标停顿时间
大堆(4GB+)Region 化设计,不受堆大小影响
服务延迟敏感G1 的停顿时间可控
避免碎片G1 每次收集后整合空间

G1 的局限性

局限性说明
吞吐量不如 Parallel GCG1 优先低延迟,吞吐量略有牺牲
大对象分配Humongous Region 分配效率低
内存占用Remembered Set 有额外开销
参数调优复杂需要理解多个参数

本节小结

G1 收集器的核心要点:

维度说明
核心思想把堆分成多个 Region,优先回收价值最高的 Region
停顿控制设置 -XX:MaxGCPauseMillis=200 目标停顿时间
空间整合无碎片,每次收集后 Region 变成 Free
分代方式逻辑分代(不强制 Eden/Survivor/Old 连续)
适用场景JDK 9+ 默认GC、低延迟服务、大堆
缺点吞吐量不如 Parallel GC

G1 是现代 JVM 的标准 GC,是大多数场景下的最佳选择。

下一节,我们来看 G1 参数设置/Region/记忆集

基于 VitePress 构建