简体中文
JVM 性能优化指南(GC 调优)
JVM 调优不是玄学,而是一个循环:测量 → 只改一件事 → 验证。本篇给你工作流、"症状 → 对策"对照表,以及真正重要的那几个参数。
第一步:动手之前先测量
永远不要盲调。先开启 GC 日志(生产安全,开销 < 3%),并分析一个覆盖业务高峰的时间窗口:
bash
# Java 9+
java -Xlog:gc*:file=gc.log:time,uptime -jar app.jar
# Java 8
java -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log -jar app.jar报告会告诉你,你面对的是下面四种典型问题中的哪一种。
第二步:症状对对策
| 报告中的症状 | 可能原因 | 尝试方案 |
|---|---|---|
| Full GC 频繁 | 老年代过小 / 内存泄漏 / 缓存过大 | 调大 -Xmx;排查泄漏(GC 后堆逐级抬升);审视缓存容量 |
| 分配速率过高 | 短命对象风暴 | 热点路径对象池化 / 缓存;减少每请求垃圾 |
| 最大停顿超过 SLO | 回收器不对或堆太大 | 换 G1/ZGC;G1 设置 -XX:MaxGCPauseMillis |
| 吞吐量 < 90% | 回收频率过高 | 加大年轻代(-Xmn / -XX:NewRatio);加大堆 |
| 元空间触发 GC | 类加载风暴 | 调大 -XX:MaxMetaspaceSize;排查动态代理 |
原因里有 System.gc() | 显式调用(RMI/NIO) | -XX:+DisableExplicitGC——先确认无 Direct ByteBuffer 依赖 |
| G1 巨型对象分配 | 对象超过分区一半 | 调大 -XX:G1HeapRegionSize;优化大数组设计 |
第三步:一次只改一个参数
调一项、重新分析、对比报告——这是确认有效性的唯一方式。覆盖 90% 场景的参数:
| 参数 | 作用 |
|---|---|
-Xms = -Xmx | 固定堆大小——消除伸缩停顿,行为更可预测 |
-Xmn / -XX:NewRatio | 年轻代大小——控制 GC 频率的主杠杆 |
-XX:+UseG1GC / -XX:+UseZGC | 回收器选择——控制停顿长度的主杠杆 |
-XX:MaxGCPauseMillis=200 | G1 停顿目标(别设得脱离现实) |
-XX:MaxMetaspaceSize | 类元数据上限 |
-XX:+DisableExplicitGC | 忽略 System.gc() 调用 |
第四步:验证并留下基线
重新分析新的 GC 日志,与旧报告对比:吞吐量升了吗?最大停顿降了吗?Full GC 消失了吗?把两份报告(PDF/JSON)存档作为基线——下次发版后分析一次,就知道 GC 行为有没有回退。
检查清单
TIP
术语还不熟?先看 JVM、JRE、JDK 的区别,再回来继续。
相关文章
- JVM 排查工具箱 — 按场景讲解 jmap、jstack、jstat 与 Arthas
- JVM 性能监控指标 — 本篇工作流所测量的数字
- 开启 GC 日志 — 一切分析的基础