G1ReservePercent是G1为老年代预留的空闲内存百分比,默认10%,专防因老年代空间不足导致的晋升失败(Promotion Failed)——即Young GC后存活对象无法晋升至老年代而触发Full GC。

什么是 G1ReservePercent,它防的是哪种“晋升失败”?
G1ReservePercent 是 G1 为老年代预留的空闲内存百分比,默认值是 10(即 10%)。它不控制新生代大小,也不影响 Young GC 行为,而是专门用来缓冲“老年代空间不足导致的晋升失败(Promotion Failed)”。这种失败发生在 Young GC 后,大量存活对象要晋升到老年代,但老年代剩余空间不足以容纳它们——此时 G1 无法完成晋升,只能触发 Full GC。
注意:这不是因为老年代“满了”,而是因为 G1 在并发标记阶段会预留一部分空间,防止在标记完成前老年代被填满。如果预留太少,标记还没结束,老年代就耗尽,就会直接退化成 Full GC。
为什么设太高反而降低堆利用率,还可能拖慢 Mixed GC?
设高 G1ReservePercent(比如调到 25)看似更安全,但实际带来两个副作用:
- 老年代可用空间变少 → 更早触发并发标记周期,Mixed GC 频率上升
- 真正能用于存放长期对象的空间被压缩 → 堆整体有效容量下降,容易提前触发老年代回收压力
例如:堆总大小 10g,G1ReservePercent=25 意味着至少 2.5g 老年代空间永远不可用。若业务对象生命周期长、晋升稳定,这部分预留就成了“沉没内存”,不仅浪费,还会让 G1 更频繁地启动 Mixed GC 去清理本可容纳的对象。
如何根据业务特征判断该设多少?
关键看老年代对象增长速率和并发标记能否跟上:
- 电商大促类场景(对象晋升突发、波动大)→ 建议
15~20,给标记留出缓冲窗口 - 实时监控/流处理类(对象生命周期短、晋升少、老年代增长平缓)→
5~10足够,避免过度预留 - 观察
G1Ergonomics日志中是否频繁出现concurrent cycle initiation提前触发,或Promotion Failed报错 → 这是调参信号
不要只看 OGC(老年代已用容量)绝对值;要结合 OGCMN/OGCMX 和 G1OldGenSize 日志估算真实可用空间,再反推预留是否合理。
和 MaxGCPauseMillis、G1HeapRegionSize 的联动关系
G1ReservePercent 不是孤立参数,它和停顿目标、Region 大小共同影响晋升稳定性:
- 当
MaxGCPauseMillis设得过低(如50),G1 会倾向于少选 Region、减少回收量 → 老年代释放变慢 → 更依赖G1ReservePercent缓冲 - 若
G1HeapRegionSize过大(如4m),单个 Region 容量高,但大对象易占满多个 Region → Humongous 分配失败风险上升,间接加剧老年代碎片与预留压力 - 没有设置
G1ReservePercent时,G1 仍会按默认值预留,但日志里不会显式打印;建议显式配置,便于追踪和灰度对比
真正难调的点在于:它不解决根本问题(比如对象泄漏或晋升过快),只是给系统加一层“保险”。一旦看到 Promotion Failed 频发,优先排查对象晋升逻辑和 Survivor 区存活率,而不是无脑拉高 G1ReservePercent。

















