G1GC
G1(Garbage First)垃圾回收器详解
G1 GC(Garbage First Garbage Collector)是 JDK 9+ 的默认垃圾回收器,设计目标是 在大内存(6GB+)、低延迟、高吞吐的场景下,提供可预测的 GC 停顿时间。
它采用了 Region 分区 和 并发回收 机制,使得 STW(Stop-The-World)停顿时间比传统 GC 更短、更可控。
⸻
G1 GC 的主要特点
- 基于 Region 进行内存管理 • 传统 GC(如 CMS)将堆分为 新生代(Young)和老年代(Old),而 G1 将整个堆划分为多个相等大小的 Region(区域),每个 Region 的大小可以动态调整。 • Region 的划分方式: • Eden(伊甸园区):新创建的对象最先分配到 Eden 区。 • Survivor(幸存区):经过多次 GC 仍存活的对象进入 Survivor 区。 • Old(老年代):在 Survivor 区存活足够长时间的对象进入 Old 区。 • Humongous(巨型对象区):存储超过 Region 大小一半的大对象。
- 并发标记,减少 STW 停顿 • G1 采用多线程并发执行垃圾回收,尽量减少应用线程的暂停时间,提高吞吐量。 • 在回收过程中,G1 优先清理垃圾最多的 Region,因此称为 “Garbage First”(垃圾优先)。
- 可预测的暂停时间 • 可以通过参数 -XX:MaxGCPauseMillis=目标时间 来设定 期望的 GC 停顿时间(默认 200ms)。 • G1 GC 会尽量满足设定的暂停时间目标,让 GC 过程更加可控。
- 避免碎片化 • G1 GC 采用混合回收,不仅回收垃圾,还会整理堆内存,避免内存碎片化,保证大对象能顺利分配。
⸻
G1 GC 运行机制
G1 GC 的垃圾回收过程分为 四个阶段:
初始标记(Initial Mark,STW) • 标记 根对象(GC Roots)可达的对象,并将其所在的 Region 设为 “需要回收”。 • 这个阶段会发生 STW,但时间很短。
并发标记(Concurrent Marking) • 在应用运行的同时,并发扫描整个堆,标记垃圾对象,计算每个 Region 的存活数据。 • 不会停止应用线程,提高性能。
最终标记(Final Mark,STW) • 在并发标记结束后,暂停应用线程,处理存活对象,确保标记信息的准确性。 • 短暂停顿(STW)。
复制清理(Evacuation) • 将存活对象复制到新 Region(Survivor/Old),释放垃圾对象所在的 Region,并进行碎片整理。 • 这一步可能导致 STW,但 G1 GC 会控制 STW 时间,避免长时间卡顿。
⸻
G1 GC 实战案例
场景
假设有一个 Java Web 应用,使用 8 核 16GB 内存的服务器,堆内存分配 8GB,期望 GC 停顿时间不超过 100ms。
JVM 配置
java -Xms8g -Xmx8g
-XX:+UseG1GC
-XX:MaxGCPauseMillis=100
-XX:InitiatingHeapOccupancyPercent=45
-XX:G1HeapRegionSize=16m
-XX:+PrintGCDetails -Xlog:gc
参数解析
参数 作用 -XX:+UseG1GC 启用 G1 垃圾回收器 -XX:MaxGCPauseMillis=100 设定 GC 目标停顿时间为 100ms -XX:InitiatingHeapOccupancyPercent=45 当整个堆使用达到 45% 时触发 GC -XX:G1HeapRegionSize=16m 每个 Region 设为 16MB -XX:+PrintGCDetails -Xlog:gc 打印 GC 详细日志
示例 GC 日志
[GC pause (G1 Evacuation Pause) (mixed), 0.091s] [Parallel Time: 85.6 ms, GC Workers: 8] [GC Worker Start (ms): Min: 53012, Avg: 53015, Max: 53018, Diff: 6] [GC Worker End (ms): Min: 53098, Avg: 53099, Max: 53100, Diff: 2] [Termination (ms): 0.5] [Other: 5.4 ms]
分析: • 这次 GC 仅暂停了 91ms,符合 -XX:MaxGCPauseMillis=100 目标。 • GC 线程数 8,说明 G1 使用多线程并行回收。 • G1 Evacuation Pause(mixed) 表示这次是混合回收(包括 Young 和 Old)。
⸻
G1 GC 的优缺点
✅ 优势 • STW 停顿时间可控(适合低延迟应用)。 • 自动整理内存,避免碎片化(不像 CMS)。 • 高吞吐量,适用于大内存场景(6GB+)。 • 支持并发回收,不影响应用运行。
❌ 劣势 • 相比 Parallel GC 吞吐量略低,适用于需要低延迟的应用,但批量计算型应用(如大数据)仍推荐 Parallel GC。 • G1 GC 可能会触发 Full GC(如果回收速度赶不上分配速度),此时 会导致长时间 STW,应合理调整 MaxGCPauseMillis。 • 比 CMS 更消耗 CPU(因为要做额外的内存整理)。
⸻
G1 GC 适用场景
适用场景 推荐理由 大堆(6GB+)的 Java 应用 G1 能有效管理大内存,避免长时间 GC 停顿 在线系统(低延迟要求) 例如 Web 服务器、微服务、数据库系统 企业级应用 Spring Boot、Tomcat、Kafka、Elasticsearch
不适用场景
不适用场景 原因 小内存应用(<4GB) G1 GC 额外的 Region 管理开销可能导致性能下降 批量计算任务 Parallel GC 提供更高的吞吐量 低 CPU 资源环境 G1 需要额外的 CPU 进行并发标记
总结 • G1 GC 采用 Region 机制,避免了 CMS 的碎片化问题。 • 通过 并发标记 + 并行回收,提供 低延迟 体验。 • 适用于大堆、低停顿的在线系统(如 Web 服务、数据库)。 • JDK 9+ 默认使用 G1 GC,推荐在 6GB+ 内存的 Java 应用 中使用。