ZGC通过实时分配速率预测回收时机:每秒采样10次TLAB与共享Region分配量,计算瞬时速率和加权平均速率;当空闲内存撑不了多久(TIMEoom)小于预期回收周期(TIMEgc)时,在下一个100ms tick触发回收,分代模式下还按年轻代/老年代分别响应。

ZGC 不靠固定时间间隔或堆占用率阈值来“拍脑袋”触发回收,而是用一套实时反馈机制,把内存分配速率作为核心输入,动态预判下一次回收该在什么时候启动。
它不是等内存快爆了才动,而是边跑边算:现在空闲多少、对象正以多快的速度被创建、按这速度还能撑多久——再跟历史回收节奏比一比,提前决策。
分配速率是ZGC的“心跳监测器”
ZGC 每秒采样一次内存分配行为(默认窗口为1秒,每秒10次抽样),持续统计线程本地缓存(TLAB)和共享 Region 的分配字节数。这些数据喂给 ZStatAllocRate 模块,生成两个关键指标:
-
_rate:最近窗口内的瞬时分配速率(单位:B/s) -
_rate_avg:加权平均后的平滑速率,削弱突发抖动影响
这个速率不是静态配置值,而是运行中不断更新的“活数据”,直接反映应用真实负载压力。
预测“OOM倒计时”与“GC倒计时”
ZGC 用两个时间量做博弈判断:
TIMEoom = 当前空闲内存(MEMfree) ÷ 当前分配速率(MEMratio)
表示:如果照当前速度分下去,空闲内存还能撑几秒。TIMEgc = 基于过去多次GC发生的时间间隔拟合出的预期回收周期
由 ZDirector 线程维护一个历史窗口(例如最近5次GC的时间戳),计算平均间隔并加入衰减因子,避免被单次长停顿拉偏。
当 TIMEoom 时,说明:按当前速度,内存耗尽会比下一次计划回收来得更早 → 必须提前触发 GC,否则有 OOM 风险。
触发动作不是立刻开始,而是“预约式启动”
满足上述条件后,ZGC 并不马上 STW 或进入标记阶段。它的典型流程是:
- 在下一个 100ms tick(由
wait_for_tick()控制)到来时检查条件 - 若仍满足,则调用
collect()启动新一轮回收周期 - 整个过程由 ZDirector 控制线程协调,ZDriver 执行具体任务
这意味着:即使某次采样发现 TIMEoom 已跌破阈值,ZGC 也会耐心等到最近一个 tick 边界再响应,既保证及时性,又避免高频抖动。
分代模式下,分配速率的影响更精细
开启 -XX:+ZGenerational 后,ZGC 不再只看全堆速率,而是分别监控年轻代和老年代的分配压力:
- 年轻代分配速率飙升 → 触发年轻代局部回收(快速复制,低开销)
- 老年代分配速率持续走高(比如大量大对象直入老年代,或年轻代晋升激增)→ 加速老年代并发标记节奏,甚至提前触发混合回收
这种分层响应,让高分配速率场景下的停顿更可控,也减少对全堆扫描的依赖。
基本上就这些。










