Skip to content

GC 性能指标/回收器发展/组合关系

GC 性能的两大核心指标

评价一个 GC 收集器的性能,主要看两个指标:

指标说明优化方向
吞吐量(Throughput)应用实际运行时间占总时间的比例单位时间内处理的任务数量
停顿时间(Latency)GC 暂停应用线程的时长单次停顿和频率
总时间 = 应用运行时间 + GC 暂停时间

吞吐量 = 应用运行时间 / 总时间

如果 GC 停顿了 10 秒,总时间是 100 秒:
吞吐量 = 90 / 100 = 90%

吞吐量 vs 停顿时间:鱼与熊掌

优化目标侧重场景
高吞吐量最大化应用运行时间批处理、数据计算
低延迟最小化单次停顿Web 服务、实时交易

现实:吞吐量和停顿时间往往是对立的——高吞吐量意味着每次 GC 回收更多对象,但停顿时间可能更长。

GC 性能指标详解

1. 吞吐量

java
public class ThroughputDemo {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        int count = 0;
        for (int i = 0; i < 1_000_000; i++) {
            count += i;
        }
        long end = System.currentTimeMillis();
        System.out.println("执行时间:" + (end - start) + " ms");
        System.out.println("吞吐量:" + (end - start) / 1000.0 + " s");
    }
}

2. 停顿时间

bash
# 打印 GC 停顿时间
java -XX:+PrintGCDetails -XX:+PrintGCApplicationConcurrentTime MyApp
# GCApplicationConcurrentTime: 99987 ms
# → 99.987 秒内没有 GC

3. 停顿频率

GC 类型停顿频率说明
MinorGC高(每分钟多次)年轻代满即触发
FullGC低(每天几次)老年代满触发
G1 MixedGC可控可设置目标停顿时间

4. Footprint(内存占用)

GC 本身的内存开销:Remembered Set、Card Table、GC 日志缓冲等。

GC 收集器的发展历程

时间线:
1995 ──→ Java 1.0 ──→ Serial GC

2002 ──→ Java 1.4 ──→ Throughput GC(Parallel GC)

2006 ──→ Java 6 ──→ CMS GC(并发标记清除)

2012 ──→ Java 7 ──→ G1 GC

2017 ──→ Java 9 ──→ G1 成为默认 GC

2018 ──→ Java 11 ──→ ZGC(可扩展低延迟 GC)

2023 ──→ Java 21 ──→ ZGC 成为默认 GC

七种经典 GC 收集器

收集器年轻代老年代算法停顿JDK 版本
SerialSerialSerial Old复制 / 标记-压缩长停顿1.3+
ParNewParNew-复制短停顿1.4+
Throughput(Parallel)Parallel ScavengeParallel Old复制 / 标记-压缩长停顿1.4+
CMSParNewCMS复制 / 标记-清除短停顿(并发)1.5+
G1G1G1复制 / 标记-清除可预测停顿7+
ZGCZGCZGC着色指针 + 读屏障亚毫秒11+
ShenandoahShenandoahShenandoah着色指针 + 转发指针亚毫秒12+

收集器组合关系

年轻代收集器 ──→ 老年代收集器(组合)

Serial ──────────────────→ Serial Old

ParNew ──────────────────→ CMS ──→ Serial Old(备选)

Throughput ──────────────→ Parallel Old

G1 ──────────────────────→ G1(独立管理年轻代和老年代)

ZGC ──────────────────────→ ZGC(统一管理)

Shenandoah ──────────────→ Shenandoah(独立管理)

常见组合

bash
# 组合一:Serial(单线程,低配机器)
java -XX:+UseSerialGC MyApp

# 组合二:ParNew + CMS(低停顿,并发)
java -XX:+UseParNewGC -XX:+UseConcMarkSweepGC MyApp

# 组合三:Throughput/Parallel(高吞吐)
java -XX:+UseParallelGC MyApp
# 等价于:-XX:+UseParallelGC -XX:+UseParallelOldGC

# 组合四:G1(平衡,JDK 9+ 默认)
java -XX:+UseG1GC MyApp

# 组合五:ZGC(超低延迟)
java -XX:+UseZGC MyApp

# 组合六:Shenandoah(低延迟)
java -XX:+UseShenandoahGC MyApp

各收集器的适用场景

场景推荐收集器原因
单核 CPU / 低配机器Serial没有线程切换开销
批处理 / 离线计算Throughput(Parallel)高吞吐量优先
Web 服务 / 在线交易G1 / ZGC低延迟优先
大堆(> 32GB)ZGC / G1ZGC 不受堆大小影响
容器 / K8sG1 / ZGC内存可控,停顿可预测
JDK 11+ 新项目ZGC最佳延迟性能
JDK 21+ 新项目ZGC(默认)JDK 21 默认 GC

收集器与代际关系的特殊说明

ParNew 和 Serial 的关系

  • Serial:年轻代 Serial = Serial Old
  • ParNew:年轻代并行(多线程版本)= Serial Old
  • ParNew 不能和 Throughput(Parallel Scavenge)组合

CMS 的退位

CMS 是 JDK 14 中正式移除的收集器(JDK 9 已标记废弃)。如果还在使用 CMS,建议迁移到 G1 或 ZGC。

G1 的统一管理

G1 不再严格区分年轻代和老年代,而是把整个堆分成多个 Region,动态调整各类型 Region 的数量。

本节小结

GC 性能指标与收集器概览:

指标含义优化方向
吞吐量应用运行时间 / 总时间高吞吐:Parallel GC
停顿时间GC 暂停的时长低延迟:G1/ZGC
停顿频率GC 发生的频率分代收集减少 FullGC

收集器选择原则:

  • 低配/单核:Serial
  • 高吞吐批处理:Throughput/Parallel
  • 低延迟服务:G1 或 ZGC
  • JDK 11+:ZGC
  • JDK 21+:ZGC(默认)

下一节,我们来看 Serial/Serial Old 回收器

基于 VitePress 构建