高并发下GC压力核心源于对象创建远超回收能力、老年代快速填满及GC停顿引发超时;应对需分层施策:选ZGC/Shenandoah、控对象生命周期、避大对象陷阱、建可观测闭环。

高并发大流量场景下,垃圾回收压力主要来自对象创建速率远超回收能力、老年代快速填满、以及GC停顿引发连锁超时。应对核心不是“压参数”,而是分层施策:选对回收器、控住对象生命周期、避开大对象陷阱、再辅以可观测性闭环。
优先选用ZGC或Shenandoah回收器
当单机QPS过万、堆内存超16GB、且接口P99延迟要求低于50ms时,G1已显吃力。ZGC(JDK 11+)和Shenandoah(JDK 12+)是更优解:
- ZGC默认支持TB级堆,停顿稳定在10ms以内,全程并发标记与移动,不依赖CPU核数增长而恶化
- 启用只需加参数:-XX:+UseZGC,搭配固定堆大小(如-Xms32g -Xmx32g),避免动态扩容抖动
- JDK 21起推荐启用分代ZGC(-XX:+ZGenerational),自动分离年轻代/老年代回收,减少扫描范围
精准控制对象分配与晋升行为
高频Minor GC本质是新生代太小或对象“活得太久”。需结合业务对象特征调整:
- 将Eden区设为堆的50%~70%,例如8GB堆可设-XX:NewRatio=1(即新生代:老年代=1:1)
- 调低晋升阈值,避免短命对象误入老年代:-XX:MaxTenuringThreshold=3(存活3次Minor GC才晋升)
- 禁用隐式大对象直接进老年代:-XX:PretenureSizeThreshold=0,强制所有对象从Eden开始分配
拦截大对象与内存泄漏源头
一个2MB的byte[]临时缓冲区,在QPS 5000时每秒就产生10GB垃圾——这比GC调优更致命:
立即学习“Java免费学习笔记(深入)”;
- 用Arthas或JFR采样分析堆中Top对象,定位高频分配点(如JSON序列化、日志拼接、缓存组装)
- 复用对象池(如Netty的PooledByteBufAllocator)替代频繁new,尤其在网络IO和序列化环节
- 检查静态集合类(如ConcurrentHashMap未清理的缓存)、未关闭的流、监听器注册未注销等典型泄漏点
建立GC可观测与响应闭环
只看GC日志不够,要让指标驱动决策:
- 开启详细日志:-Xlog:gc*,gc+heap=debug,gc+ergo*=info:file=gc.log:time,tags,uptime(JDK 10+新格式)
- 接入Prometheus + Grafana,监控关键指标:Young GC频率、平均暂停时间、老年代使用率、晋升速率
- 设置告警:老年代使用率持续>85%、单次GC停顿>50ms、Full GC每小时>3次,立即触发人工介入


















