jvm内存调优核心是依据吞吐量(≥95% web/≥99%批处理)、停顿时间(minor gc 10–50ms、full gc避免>200ms)、内存回收效率(eden清空率、老年代缓慢上升、元空间不持续增长)及gc频率(minor gc每分钟≤5次、杜绝full gc)等可观测指标动态优化。

JVM 内存调优不是调参数本身,而是让参数服务于真实业务表现。关键不在“堆设多大”,而在“这些数字是否说明系统健康”。性能指标就是你的判断依据,必须盯住几个核心、可观测、可归因的数值。
吞吐量(Throughput)
这是应用真正干活的时间占比,公式是:运行时间 ÷(运行时间 + GC 时间)。比如一小时内,应用实际执行业务逻辑 3540 秒,GC 占了 60 秒,吞吐量就是 3540/3600 ≈ 98.3%。
- Web 服务通常要求 ≥95%,批处理作业建议 ≥99%;
- 如果吞吐量持续低于 90%,大概率是 GC 频繁或单次耗时过长;
- jstat -gc PID 输出中的
GCT(总 GC 时间)和GC count是直接计算来源。
停顿时间(GC Pause / STW)
每次 GC 导致应用线程全部暂停的时长,尤其影响用户体验。重点关注:
- Minor GC 停顿是否稳定在 10–50ms(新生代回收);
- Full GC 或老年代 GC 是否出现 >200ms 的长停顿(需立即干预);
- G1/ZGC 的
MaxGCPauseMillis是目标值,但实际值要看 GC 日志中Pause字段,例如Pause Young (Mixed)后面的毫秒数; - 使用
-Xlog:gc*:file=gc.log:time,level输出的日志,可直接 grepPause统计分布。
内存使用趋势与回收效率
光看瞬时占用没意义,要观察动态行为:
- 新生代每次 Minor GC 后,Eden 区是否基本清空(理想情况是
- 老年代使用率是否缓慢上升(健康)、陡升(对象提前晋升或内存泄漏)、或反复高位震荡(频繁 Major GC);
- 元空间(Metaspace)使用量是否持续增长且不回落,配合
jstat -gcmetacapacity PID判断是否类加载泄漏; -
jmap -histo:live PID可快速识别长期驻留的大对象或异常膨胀的集合类(如 HashMap、ArrayList 实例数突增)。
GC 频率与类型分布
频率比绝对次数更重要,需结合业务节奏判断:
- 每分钟 Minor GC 超过 3–5 次,通常说明新生代太小或对象生命周期偏长;
- 出现 Full GC(或 G1 中的 Full GC 等效事件),哪怕每周一次也属严重问题;
- G1 中 Mixed GC 过于频繁(如每分钟多次),说明老年代碎片化或晋升阈值不合理;
- 用
jstat -gc PID 1000 10(每秒采样 10 次)可直观看到 GC 类型和间隔波动。
不复杂但容易忽略











