serial old 与 zgc 的 gc 压力表现差异源于设计目标根本不同:serial old 是单线程全暂停标记-整理回收器,面对复杂对象图时标记和整理均需 stw 且耗时线性增长;zgc 则通过并发标记、按 region 并发转移及染色指针实现亚毫秒停顿,压力分散、天然适配大堆深图场景。

Serial Old 和 ZGC 在复杂对象图上的 GC 压力表现差异极大,根本原因不在“谁更先进”,而在于设计目标与执行模型完全不同:Serial Old 是单线程、全暂停、标记-整理式的老年代回收器;ZGC 是全并发、亚毫秒级停顿、基于区域(Region)和染色指针的现代低延迟回收器。两者几乎不在同一维度上竞争。
Serial Old 的压力瓶颈非常明确
面对深度嵌套、跨代引用多、对象图拓扑复杂的场景(比如大量相互引用的 DTO、树形结构缓存、长生命周期的上下文对象),Serial Old 会暴露三个硬性限制:
- 标记阶段耗时线性增长:它必须 STW 遍历整个老年代对象图,图越复杂、引用链越深,标记时间越长——几十万对象就可能触发数百毫秒甚至秒级停顿。
- 整理阶段无法并发:存活对象迁移需逐个复制+更新引用,且所有引用更新必须在 STW 中完成。复杂图中跨 Region 或跨代指针越多,更新成本越高。
- 无增量或分块处理能力:不能拆解任务,也不能跳过暂不活跃子图。一次 Full GC 就是“全量重扫 + 全量搬迁”,压力集中爆发。
ZGC 的压力应对逻辑完全不同
ZGC 不试图“一口气做完”,而是把压力分散到多个并发阶段,尤其擅长应对大图、深图、高交叉引用的场景:
- 并发标记全程不停顿:使用读屏障(Load Barrier)配合染色指针,在应用线程运行中渐进标记;即使对象图再复杂,也不会导致 STW 延长。
- 并发转移(Relocation)按 Region 粒度推进:只搬当前最“热”或最“碎片化”的 Region,不强制扫描全局图;复杂引用关系由转发指针(Forwarding Pointer)和读屏障透明处理。
- 停顿只发生在极短的“初始化标记”和“最终转移”两个小同步点:无论堆是 4GB 还是 4TB,无论对象图含 100 万还是 1 亿节点,典型停顿稳定在 1ms 内。
实际压力测试中的关键观察点
若真要做对比测试,建议关注以下可量化指标,而非单纯看“是否 OOM”或“是否卡死”:
- STW 时间分布:Serial Old 的 Full GC 停顿呈强正态分布,尾部可能超 1s;ZGC 的停顿始终集中在 0.1–0.8ms 区间,无明显长尾。
- GC 吞吐占比:Serial Old 在高图复杂度下,GC 时间可能占总运行时间 15%+;ZGC 通常控制在 2% 以内,且随堆增大不显著上升。
- 内存碎片敏感度:Serial Old 整理后碎片率趋近于 0,但代价是长时间停顿;ZGC 依赖 Region 分配,天然抗碎片,但极端场景下可能触发额外的“回收失败”降级路径(极少发生)。
选型不是技术比武,而是场景匹配
Serial Old 适合堆小(≤200MB)、对象图简单、允许秒级停顿的嵌入式或工具类程序;ZGC 专为堆大(≥4GB)、图复杂、延迟敏感(如实时风控、高频交易、互动直播)而生。拿 Serial Old 去压测 ZGC 的适用场景,就像用算盘跑 AI 推理——不是它不行,是它根本没被设计干这事。











