G1(Garbage-First)是JVM中一款兼顾吞吐量与延迟的垃圾收集器,由Oracle在Java 7中引入(Java 9后成为默认GC),专为大堆内存(通常4GB以上)设计,核心目标是在可控的停顿时间内高效回收垃圾。
一、G1的核心原理
G1的设计围绕"Region化管理"和"优先级回收"展开,核心机制包括:
1. Region化内存布局
G1将堆内存划分为多个大小相等的独立Region (默认1MB~32MB,需为2的幂,可通过-XX:G1HeapRegionSize
调整),每个Region可动态标记为以下类型:
- Eden Region:存放新创建的对象(年轻代);
- Survivor Region:存放经历一次GC后存活的年轻代对象;
- Old Region:存放老年代对象(存活时间较长的对象);
- Humongous Region:存放大对象(大小超过Region的50%),由连续的Region组成(避免大对象跨Region存储)。
这种布局打破了传统GC"年轻代、老年代物理隔离"的限制,通过Region动态角色切换实现灵活回收。
2. Mixed GC(混合回收)
G1的核心创新是"优先回收垃圾最多的Region"(Garbage-First的由来),其GC过程分为两种:
- Young GC:仅回收Eden和Survivor Region,类似其他分代GC的年轻代回收,会导致短暂停顿;
- Mixed GC :不仅回收年轻代Region,还会选择部分老年代Region(垃圾占比高的)一起回收,通过这种"混合回收"逐步清理老年代,避免传统Full GC的长时间停顿。
3. Remembered Set(记忆集)
为解决跨Region引用的追踪问题(如Old Region引用Eden Region的对象),G1为每个Region维护一个Remembered Set(RS):
- 当一个Region中的对象引用另一个Region的对象时,会在目标Region的RS中记录这个引用关系;
- GC时,通过扫描RS即可快速定位跨Region的存活对象,避免全堆扫描,减少开销。
4. 停顿预测模型(Pause Prediction Model)
G1允许用户设置目标最大停顿时间 (如-XX:MaxGCPauseMillis=200
,默认200ms),内部通过历史GC数据预测:
- 哪些Region垃圾最多、回收成本最低(耗时短但回收内存多);
- 动态调整本次GC回收的Region数量,确保实际停顿时间接近目标值。
5. GC过程(简化版)
G1的完整GC流程包括:
- 初始标记(Initial Mark):标记根对象(如线程栈、静态变量),伴随短暂停顿(通常<10ms);
- 并发标记(Concurrent Mark):从根对象出发,遍历并标记所有存活对象(与应用线程并行,无停顿);
- 最终标记(Final Mark):处理并发标记期间遗漏的引用(如线程本地缓存中的对象),停顿时间较短;
- 筛选回收(Live Data Counting & Evacuation):根据停顿目标,选择垃圾占比高的Region,将存活对象复制到新Region(消除碎片),伴随停顿(时间由目标停顿时间控制)。
二、G1的使用方法
启用G1需满足JDK 7及以上版本,核心JVM参数如下:
bash
# 启用G1垃圾收集器
-XX:+UseG1GC
# 设置最大堆内存(G1适合4GB以上大堆)
-Xmx16g
# 设置目标最大停顿时间(毫秒,G1会尽量接近该值)
-XX:MaxGCPauseMillis=100 # 示例:目标停顿不超过100ms
# 其他常用参数
-XX:G1HeapRegionSize=4m # 每个Region的大小(1M~32M,需为2的幂)
-XX:G1NewSizePercent=5 # 年轻代最小占比(默认5%)
-XX:G1MaxNewSizePercent=60 # 年轻代最大占比(默认60%)
-XX:G1ReservePercent=10 # 预留内存占比(防止晋升失败,默认10%)
三、G1的优势
- 兼顾延迟与吞吐量:通过Mixed GC和停顿预测模型,既能控制单次GC停顿时间(通常<200ms),又能保证较高的吞吐量(优于CMS,接近ParallelGC),适合需要平衡两者的场景。
- 适合大堆内存:Region化管理使G1能高效处理大堆(4GB~数百GB),避免传统GC在大堆下的长停顿。
- 减少内存碎片:筛选回收阶段通过复制存活对象到新Region,自动整理内存,长期运行碎片率低(优于CMS)。
- 动态适应性强:无需手动划分年轻代/老年代大小,G1会根据应用特性自动调整各Region比例,降低调优门槛。
四、G1的劣势
- 内存开销较高:Remembered Set需占用额外内存(通常为堆大小的5%~10%),且维护RS的写屏障操作会消耗CPU资源。
- 小堆场景性能一般:在小堆(<4GB)下,G1的Region管理和RS维护开销占比过高,性能可能不如ParallelGC或SerialGC。
- 调优复杂度:虽然默认参数适用多数场景,但极端情况下(如大对象频繁分配、停顿时间不达标)需调整多个参数(如Region大小、年轻代比例),调优难度高于ParallelGC。
- 仍可能触发Full GC:若Mixed GC回收速度赶不上对象晋升速度(如大量对象快速进入老年代),G1会触发Full GC(单线程标记-清除-整理),导致长时间停顿(秒级)。
五、适用场景
- 推荐场景:中等至大型堆内存(4GB以上)、需要平衡延迟与吞吐量的应用(如企业级Web服务、电商系统、CRM系统)。
- 不推荐场景:小堆内存(<4GB)、对吞吐量要求极高而延迟不敏感的批处理任务(此时ParallelGC更优)、超大堆(>100GB且延迟要求亚毫秒级,此时ZGC更合适)。
总结
G1是一款"平衡型"垃圾收集器,通过Region化管理和优先级回收,在大堆场景下实现了延迟与吞吐量的有效折中,是Java 9+的默认选择。但需注意其内存开销和小堆场景的局限性,实际使用中需结合堆大小、业务延迟需求进行参数调优。