jvm垃圾回收器性能必须在真实负载下验证,核心是评估其在特定并发下的吞吐量、停顿时间(关注p99)和回收频率三指标的平衡表现,而非单纯选择回收器类型。

JVM垃圾回收器的性能表现,必须放在真实负载下验证。脱离压力测试谈GC指标,容易误判系统真实瓶颈。核心不是“用哪个回收器”,而是“在多大并发下,它是否满足你的吞吐、延迟和稳定性要求”。
关键性能指标怎么看
三个硬性指标相互制约,无法同时最优:
- 吞吐量:用户代码执行时间占总时间的比例。比如运行1小时,GC耗时3分钟,吞吐量≈95%。金融类后台常要求≥99%,Web接口类可接受97%~98%。
- 停顿时间(STW):每次GC导致业务线程暂停的时长。G1默认目标200ms以内,ZGC承诺≤10ms(无论堆多大)。注意:平均停顿低≠没有长尾——要关注99线(P99)而非平均值。
- 回收频率:单位时间内GC次数。Minor GC每秒几次属正常;Full GC每小时超过1次,基本说明堆配置或对象生命周期有问题。
压测必须覆盖的真实场景
只跑单接口、不模拟真实流量模式,压测结果参考价值极低:
- 混合读写比例:如电商下单链路包含查库存(读)、扣减(写)、发消息(异步),需按实际比例配比请求类型。
- 对象生命周期波动:短生命周期对象(如DTO)大量创建销毁,易触发Young GC;长生命周期缓存对象堆积,则考验Old区回收效率。
- 突发流量与持续压测结合:先用JMeter ramp-up 2分钟到峰值,稳态运行10分钟观察GC趋势;再叠加一次3秒脉冲流量,看ZGC/G1能否扛住瞬时晋升压力。
常用工具与命令组合
不要只靠图形界面,命令行+日志才是定位根因的关键:
-
jstat -gc
1000 10 :每秒输出10组GC统计,重点关注YGC/YGCT(年轻代次数/耗时)、FGC/FGCT(Full GC次数/耗时)、GCT(总GC时间)。 -
jcmd
VM.native_memory summary :确认是否元空间、直接内存泄漏,避免误判为堆GC问题。 - -Xlog:gc*,gc+heap=debug:file=gc.log:time,tags:filecount=5,filesize=50m:开启结构化GC日志(JDK11+),配合GCViewer或gceasy.io做可视化分析。
- 压测时同步采集:top -Hp
看GC线程CPU占用,free -h确认系统内存是否被其他进程挤压。
回收器选型不能只看文档
实测中常见反直觉现象:
- G1在堆<4GB且停顿敏感场景下,可能不如Parallel Old稳定;ZGC在JDK17+才真正成熟,JDK15/16存在部分JNI调用兼容问题。
- 高吞吐场景(如批处理)优先选Parallel GC,参数简单(-XX:+UseParallelGC),调优空间小但稳。
- 若应用存在大量大对象(>2MB),G1的Humongous Allocation易引发碎片和额外GC,此时ZGC或Shenandoah更合适。
- 启用ZGC必须确保操作系统支持大页(Transparent Huge Pages建议关闭,改用Explicit Huge Pages),否则反而增加延迟。











