mixed gc正常需并发标记周期完整完成,若缺失initial-mark等阶段或出现“concurrent cycle was cancelled”则存在退化风险;需结合eden清零、survivor变化、老年代回收效果、real停顿时间及子阶段耗时、异常提示词综合判断。

看到 G1 的 Mixed GC 日志,关键不是认出“mixed”这个词,而是快速判断它是否正常、有没有隐藏风险。
看日志类型和触发原因
日志里明确带 (mixed) 就是 Mixed GC。但它不是独立发生的,背后一定有并发标记周期完成的支撑。如果日志中紧挨着出现 initial-mark → concurrent-mark → remark → cleanup,再跟上 (mixed),说明流程完整;若 mixed 突然频繁出现但前面没看到完整的标记阶段,可能是并发标记被取消(日志里会有 Concurrent Cycle was cancelled),这时 Mixed GC 实际是“带病上岗”,容易引发退化。
盯住空间变化数字
一行典型日志像这样:[GC pause (G1 Evacuation Pause) (mixed), 0.162s] [Eden: 1024M→0B, Survivors: 128M→128M, Heap: 2800M→1650M]
- Eden 从满到清零:说明年轻代回收按预期执行
- Survivor 大小不变甚至涨了:可能对象存活率高,或晋升阈值偏低,导致本该留在 Survivor 的对象被推去老年代
- Heap 总量下降但老年代没明显减少:比如 Heap ↓1150M,但老年代只 ↓200M,其余全靠 Eden 贡献——说明选入 CSet 的老年代 Region 回收效果差,可能是这些 Region 存活率太高,或者根本没选对“高价值”区域
重点看 real 停顿时间和子阶段耗时real=0.162s 是真实 STW 时间,超过 200ms 就要警惕。展开子阶段看哪块拖后腿:
-
Ext Root Scanning突增(比如从 2ms 跳到 40ms+):线程数暴增、反射/动态代理类过多 -
Object Copy时间长:存活对象多,常见于 Survivor 过小、大对象集中、或G1MixedGCLiveThresholdPercent设得过高(默认 85%),把本该跳过的高存活 Region 也塞进去了 -
Update RS或Processed Buffers高:RSet 更新压力大,说明跨 Region 引用频繁,可能业务存在大量弱引用缓存或 Map 类结构持有跨代引用
留意异常提示词
- 出现
to-space overflow或evacuation failed:说明 Region 搬迁失败,大概率触发 Full GC,需检查-XX:G1HeapRegionSize是否太小,或是否存在持续分配超大数组 -
Humongous Allocation同时出现在 mixed 行:大对象正在干扰混合回收节奏,关注HumongousOccupiedCount是否单边上涨 -
reclaimable=15.2%(在G1-Evacuation-Info行)低于默认 20% 阈值:这批老年代 Region 回收性价比低,G1 可能很快放弃 Mixed GC,转向保守策略
基本上就这些。










