高并发场景下JVM垃圾回收核心是匹配业务节奏:短命对象应留在Eden区由Minor GC快速清理,避免过早晋升;长稳对象需防止被意外强引用拖累效率;G1(-XX:MaxGCPauseMillis=200)为中大型服务主流选择,ZGC适用于超低延迟要求。

高并发场景下,JVM 垃圾回收不是“越少越好”,而是要让 GC 行为与业务节奏匹配——既要避免频繁停顿拖垮响应,又不能因过度抑制 GC 导致内存持续膨胀、最终触发长时间 Full GC 或 OOM。
看准对象生命周期特征
高并发服务(如订单创建、实时风控)通常有两类典型对象:
- 短命对象多:比如一次 HTTP 请求产生的 DTO、临时集合、日志上下文等,98% 在几毫秒内就不可达。这类对象应尽量留在 Eden 区完成回收,靠 Minor GC 快速清理,不希望它们过早晋升到老年代。
- 长稳对象少但关键:如连接池、缓存容器、配置单例、线程安全的共享状态等。它们该长期存活,但必须确保不被意外强引用拖累新生代回收效率(例如静态 Map 持有请求对象)。
若发现 Survivor 区反复复制后仍大量对象晋升,说明对象存活时间超出预期,需检查是否业务逻辑误延长了对象生命周期(如缓存未设 TTL、ThreadLocal 泄漏)。
选对收集器并设合理目标
不是参数调得越激进越好,关键是让 GC 的停顿和频率落在业务可接受区间内:
-
G1 是当前主流选择:适用于堆 4GB~64GB 的中大型服务。用
-XX:+UseG1GC启用后,重点控制-XX:MaxGCPauseMillis=200(目标停顿 200ms),JVM 会自动调整年轻代大小、Region 数量和回收时机来逼近该目标。 -
别硬压 NewRatio:手动设
-XX:NewRatio=3强制老年代占比,在高并发波动场景下反而容易导致年轻代过小 → Minor GC 频繁,或过大 → 晋升压力集中爆发。G1 默认自适应调节更稳妥。 - 超低延迟可试 ZGC:若服务 SLA 要求 P99 响应
管住元空间和非堆内存
高并发常伴随动态类加载(如热更新、脚本引擎、Spring Boot DevTools),容易引发元空间暴涨:
- 加
-XX:+UseContainerSupport(尤其在 Docker/K8s 环境),让 JVM 正确识别容器内存限制; - 设
-XX:MaxMetaspaceSize=256m防止无节制增长,配合-XX:+PrintGCDetails观察 Metaspace GC 频次; - 警惕 JNI、DirectByteBuffer、CompressedOops 外的本地内存占用,它们不归 GC 管,但会挤占系统资源,造成假性 OOM。
用监控定策略,而不是凭感觉调参
上线前后的 GC 行为差异,往往比代码改动影响更大:
- 必开
-Xlog:gc*:file=gc.log:time,tags,level(JDK 11+)或-XX:+PrintGCDetails -XX:+PrintGCDateStamps(旧版),分析 GC 频率、停顿分布、晋升速率、碎片率; - 关注 GC 吞吐量(应用线程运行时间 / 总时间) 和 最大单次停顿,前者低于 95% 或后者突破业务容忍阈值,就是调优信号;
- 结合 Arthas、Prometheus + Grafana 或 JFR(Java Flight Recorder)做热点方法+内存分配追踪,确认是 GC 问题,还是对象本身创建不合理(如循环中 new HashMap)。



















