g1 young gc通过动态预测模型实时调整eden region数量,依据历史停顿时间、存活对象量和晋升速率,在-xx:g1newsizepercent与-xx:g1maxnewsizepercent间自适应增减,目标是逼近-xx:maxgcpausemillis设定值。

G1 的 Young GC 不是固定 Eden 区大小的静态回收,而是靠一套基于历史停顿数据的动态预测模型实时决定本次该用多少个 Eden Region。它不依赖预设比例,而是每轮 YGC 后根据实际耗时、存活对象量、晋升速率等反馈,主动增减 Eden 区数量,目标是让单次 Young GC 尽量贴近 -XX:MaxGCPauseMillis 设定的停顿上限。
预测模型依赖三个核心输入
这个模型不是凭空估算,而是持续跟踪并加权计算:
- 最近几次 Young GC 的实际 STW 时间(来自 jstat 或 GC 日志中的 pause 时间),用衰减平均值(davg)和标准偏差(dsd)建模波动性
- 本次 YGC 前 Eden 区总大小与其中存活对象量(即 evacuation 后需复制的数据量),直接影响复制耗时
- 上一轮 Young GC 的晋升量(Promotion Rate),若大量对象直接升入老年代,说明 Survivor 容量或 Tenuring Threshold 不足,模型会倾向扩大 Eden + Survivor 总 Region 数以缓冲压力
Eden Region 数量如何被“增”或“减”
调整动作发生在每次 Young GC 完成后,由 G1 的自适应逻辑触发:
- 若本轮 YGC 实际耗时明显低于目标(比如目标 200ms,实测仅 120ms),且 Eden 使用率长期高于 85%,模型判断“还有余量”,下一轮就会增加若干 Eden Region(通常 +1~3 个),提升吞吐
- 若连续两次 YGC 耗时逼近或超过目标(如 195ms、210ms),或观察到 YGCT/YGC 比值 > 80ms(jstat 输出),说明 Eden 被撑得太满、频繁触发小规模回收,模型会主动削减 Eden Region 数量,降低单次工作量
- 新生代总 Region 数被硬性约束在 -XX:G1NewSizePercent=20 到 -XX:G1MaxNewSizePercent=50 之间,超出范围的调整会被截断——收窄这个浮动区间,能有效抑制 Eden 忽大忽小带来的 pause 波动
Region 粒度本身影响预测精度
预测是否靠谱,前提是 Region 大小合理:
- Region 过大会导致单 Region 回收时间不可控(比如默认 4MB Region 在大堆中可能要 30ms 才能 copy 完),让模型“失焦”;建议堆 ≤32GB 时让 JVM 自动选(通常 1~2MB),32GB 以上且对象偏大才显式设 -XX:G1HeapRegionSize=4m
- Region 总数应 ≥2048,太少(如 512 个)会倒逼单 Region 变大,削弱 G1 “按价值精细挑选”的能力;可用 -Xmx64g -XX:G1HeapRegionSize=4m 得到 16384 个 Region
- 避免 Region 过小(如 1MB 配 64GB 堆 → 65536 个 Region),Remembered Set 元数据爆炸式增长,反而拖慢并发标记阶段,间接干扰 Young GC 的调度节奏
冷启动期需要耐心
新应用刚启动时,模型还没“学会”你的业务特征:
- 前 5~10 次 Young GC 属于预热,davg/dsd 未收敛,停顿容易超标(如设 200ms,实测达 280ms)
- 建议上线初期开启 -Xlog:gc*,safepoint,重点看 Evacuation Pause 中 evacuation 和 root region scanning 阶段耗时分布,而非只盯总 pause
- 稳定运行约 20 次 GC 后,模型才具备较准的预测能力,此时再结合业务峰值期的实际表现做参数微调更可靠











