g1通过region分区与增量回收实现可控停顿:将堆划分为约2048个大小相等的region,动态分配角色,优先回收垃圾最多、收益最高的region集合(cset),结合young gc与mixed gc,使stw时间贴近-xx:maxgcpausemillis设定目标。

G1垃圾回收器通过把堆切成固定大小的Region,每次只回收其中垃圾最多、收益最高的几个区域,从而把停顿时间控制在你设定的目标范围内。它不是靠“扫完整个堆”来工作,而是靠“精准挑选+增量清理”,这是它能替代CMS成为默认GC的根本原因。
Region分区与动态角色分配
G1把整个Java堆划分为2048个左右大小相等的Region(默认1MB~32MB,由堆总大小自动推算)。每个Region在逻辑上可以是Eden、Survivor或Old,角色不固定,随回收需要动态切换。这种设计打破了传统新生代/老年代物理隔离的限制,让内存使用更灵活,也使跨代引用处理更高效。
- 新对象优先分配到Eden型Region;
- 年轻代GC后存活对象复制到Survivor型Region;
- 达到年龄阈值或大对象(超过Region一半)直接进入Old型Region;
- 没有连续的老年代空间,也就不存在CMS那种因碎片导致的Full GC灾难。
停顿时间可控的核心机制
G1的停顿目标(如-XX:MaxGCPauseMillis=200)不是承诺值,而是调度依据。它会根据历史GC数据预测每个Region的回收耗时和收益,每次选一组Region组成CSet(Collection Set),确保STW阶段总时间尽量贴近目标。
- 年轻代GC:只处理所有Eden+Survivor Region,停顿较短且稳定;
- 混合GC:在并发标记完成后触发,同时回收部分Eden、Survivor和Old Region;
- 并发标记阶段本身基本不STW,只在初始标记和最终标记两个小环节暂停应用线程。
关键调优参数与常见误区
调优G1不是堆参数越多越好,重点盯住三个杠杆:停顿目标、并发标记触发时机、Region大小。
- -XX:MaxGCPauseMillis=200:设太低(如50ms)会导致频繁GC、吞吐下降;设太高(如500ms)失去G1优势,建议150~300ms起步;
- -XX:InitiatingHeapOccupancyPercent=45:老年代占用达45%才启动并发标记,偏高易引发“并发模式失败”,可下调至35~40;
- -XX:G1HeapRegionSize=2M:默认自动计算,但若堆为8GB,Region可能为2MB,此时大对象(如6MB缓存)会横跨多个Region,影响回收效率,可显式设为4M对齐;
- 避免设置-XX:G1NewSizePercent等人为干预比例的参数——G1自己会根据负载动态调整年轻代占比,硬指定反而破坏自适应能力。
线上问题排查抓手
看GC日志,重点关注三类信号:
- 频繁Mixed GC但回收量很小 → 老年代碎片多或存活对象多,检查是否有缓存未释放、静态集合持续增长;
- 出现Concurrent Mode Failure → 并发标记没跑完,老年代就满了,说明IHOP设太高或分配速率突增;
- 单次GC停顿远超目标 → 可能发生Evacuation Failure(复制失败)、Humongous Allocation(巨型对象分配)或元空间不足触发额外GC。











