“to-space exhausted”表明g1混合回收失效,需结合日志阶段、指标趋势与配置失配三方面定位断层:young gc中出现说明survivor区不足致对象直入老年代;mixed gc中出现则反映老年代碎片化或空间耗尽导致疏散失败。

“To-space exhausted”不是一次普通的 GC 异常,而是 G1 回收链在年轻代→幸存区→老年代传导过程中出现断裂的明确信号。它直接暴露混合回收(Mixed GC)已失去对老年代空间的有效调控能力,必须从日志上下文、触发阶段和配置失配三方面交叉定位断层根源。
识别 To-space exhausted 出现的真实阶段
不能孤立看这一条日志,需结合 GC 类型和前后行为判断断层位置:
- 若出现在 Young GC 日志中(如
[GC pause (G1 Evacuation Pause) (young) (to-space overflow)]),说明 Survivor 区(to-space)容量不足,对象无法完成复制周转,被迫跳过晋升年龄阈值,直接进入老年代 - 若出现在 Mixed GC 日志中(如
[GC pause (mixed) ... (to-space exhausted)]),表明老年代已严重碎片化或空间耗尽,G1 在尝试将年轻代存活对象晋升时,找不到足够连续的老年代 Region 容纳,导致疏散失败 - 伴随
Concurrent Cycle Abort或Full GC after mixed GC,说明并发标记周期已被迫中断,Mixed GC 彻底失效,系统已退化为 STW 式 Full GC
关联关键指标验证断层影响
单条日志只是表象,需观察趋势性指标确认是否形成恶性循环:
-
老年代回收效率骤降:Mixed GC 日志中老年代回收量长期低于堆总大小的 3%,例如
800M->795M(1024M)(仅回收 5MB),说明大量“早产对象”堆积,标记-清除效率崩溃 -
晋升年龄异常偏低:在 Young GC 日志的
age字段中,发现大量对象在 age=1 或 age=2 就晋升,远低于默认的 MaxTenuringThreshold=15,证实 Survivor 区根本未起作用 -
Mixed GC 频次激增但收效甚微:日志中连续出现多个 Mixed GC,每次仅回收极少量老年代 Region,且
candidate old regions数量持续接近G1OldCSetRegionThresholdPercent上限,说明 G1 被迫反复尝试却无法释放有效空间
定位三类典型配置失配
断层本质是 G1 的自动调优机制被人为配置覆盖或参数间逻辑冲突:
-
硬编码 Survivor 大小:误配
-XX:SurvivorRatio或-XX:NewRatio会锁定 Survivor 区固定大小,剥夺 G1 动态伸缩能力;应完全移除这两项,交由 G1 自主管理 -
晋升阈值与并发标记启动时机不匹配:MaxTenuringThreshold 过高(如保持默认 15),但 Survivor 实际容量不足,导致第 1 次 Young GC 就强制晋升;应结合日志中真实晋升 age,设为 3~5,并同步降低
-XX:InitiatingHeapOccupancyPercent(如从 45% 调至 35%),让并发标记更早介入 -
Region 尺寸与堆规模不协调:例如 4GB 堆使用默认 2MB Region(共 2048 个),Survivor 最多分到 4 个 Region(8MB),无法承载中等流量下的对象周转;可通过
-XX:G1HeapRegionSize=4M减少 Region 总数,扩大单个 Survivor 容量
验证优化是否真正闭环
调参后不能只看某次 GC 是否消失,需确认三个指标同步收敛:
- Young GC 日志中
to-space overflow和Evacuation Failure归零 - Mixed GC 中老年代回收比例稳定回升至 10% 以上,且
reclaimable字段数值显著增大 - 不再出现
Concurrent Mark Abort或Full GC after mixed GC,并发标记周期能完整执行并自然触发 Mixed GC











