优先压低stw时间,核心是启用g1回收器(-xx:+useg1gc)、设定目标停顿(-xx:maxgcpausemillis=150–250)、固定堆大小(-xms=-xmx)、合理配置新生代与region参数,并通过gc日志持续验证。

响应延迟高,往往不是 GC 频繁,而是单次 GC 停顿时间太长。优化方向很明确:优先压低 STW(Stop-The-World)时间,其次控制 GC 频率,核心是选对回收器 + 合理配置关键参数。
用 G1 回收器替代默认回收器
多数 Java 应用默认使用 Parallel GC 或 Serial GC,它们在大堆、高并发下容易出现几百毫秒甚至秒级停顿。G1 是 JDK 9+ 默认回收器,专为可控停顿设计。
- 启用 G1:
-XX:+UseG1GC - 设定目标停顿上限(非绝对保证,但强约束):
-XX:MaxGCPauseMillis=200(建议 150–250ms 区间) - 若堆大于 4GB,可显式设 Region 大小提升效率:
-XX:G1HeapRegionSize=2m或4m(避免过大或过小)
固定堆大小并合理分配新生代
动态扩容会触发额外 GC,且堆比例失衡易导致对象过早晋升、老年代碎片化,加剧 Full GC 风险。
- 初始与最大堆一致:
-Xms4g -Xmx4g(按实际负载定,常见 2–8g) - 避免靠 NewRatio 算比例,直接指定新生代大小更可控:
-Xmn1g(即新生代 1GB,老年代自动为 3GB) - Survivor 区不宜过小,防止 minor GC 后对象“挤”进老年代:
-XX:SurvivorRatio=6(Eden:Survivor = 6:1:1)
调优晋升与大对象行为
频繁 minor GC 后对象立即晋升,或大对象直接进老年代,都会快速填满老年代,触发 costly 的 mixed GC 或 Full GC。
- 降低晋升年龄阈值,让短期对象更早被回收:
-XX:MaxTenuringThreshold=6(默认 15,6–8 更适合短生命周期业务) - 限制大对象直接入老年代的尺寸(避免小对象误判):
-XX:PretenureSizeThreshold=1048576(即 1MB,需结合业务对象大小调整) - 提前触发并发标记周期,避免老年代突然爆满:
-XX:InitiatingHeapOccupancyPercent=40(默认 45,略下调更稳妥)
开启日志并持续验证效果
不看日志,所有调优都是猜测。必须开启详细 GC 日志,观察停顿分布、晋升速率、混合回收频率。
- 基础日志:
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/path/gc.log - 推荐增强项:
-XX:+PrintTenuringDistribution(看对象年龄分布)、-XX:+UseGCLogFileRotation(自动轮转防日志撑爆磁盘) - 用 GCViewer 或 JDK 自带
jstat -gc <pid></pid>实时监控,重点关注G1-YGC平均耗时和G1-Full-GC是否归零
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











