系列导读:本篇将深入讲解 JVM 调优的核心原理及实战过程中注意事项。
文章目录
-
- [一、JVM 内存模型](#一、JVM 内存模型)
-
- [1.1 内存结构](#1.1 内存结构)
- [1.2 内存参数](#1.2 内存参数)
- 二、垃圾回收器
-
- [2.1 GC 对比](#2.1 GC 对比)
- [2.2 G1 配置示例](#2.2 G1 配置示例)
- [2.3 ZGC 配置示例](#2.3 ZGC 配置示例)
- 三、调优主要参数
-
- [3.1 内存配置](#3.1 内存配置)
- [3.2 GC 配置](#3.2 GC 配置)
- [3.3 日志配置](#3.3 日志配置)
- 四、问题诊断
-
- [4.1 常用工具](#4.1 常用工具)
- [4.2 OOM 排查](#4.2 OOM 排查)
- [4.3 CPU 飙高排查](#4.3 CPU 飙高排查)
- 五、实战案例
-
- [5.1 案例:Full GC 频繁](#5.1 案例:Full GC 频繁)
- [5.2 案例:内存泄漏](#5.2 案例:内存泄漏)
- 总结
一、JVM 内存模型
1.1 内存结构
┌─────────────────────────────────────────────────────────────┐
│ JVM 内存结构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 堆 (Heap) │ │
│ │ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ 新生代 │ │ 老年代 │ │ │
│ │ │ Eden+Survivor│ │ (Old) │ │ │
│ │ └─────────────┘ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 方法区 (Metaspace) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 程序计数器│ │虚拟机栈 │ │本地方法栈 │ │ 直接内存 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
JVM 内存结构(分代模型)图:

1.2 内存参数
| 参数 | 说明 |
|---|---|
| -Xms | 初始堆大小 |
| -Xmx | 最大堆大小 |
| -Xmn | 新生代大小 |
| -XX:MetaspaceSize | 元空间初始大小 |
| -XX:MaxMetaspaceSize | 元空间最大大小 |
二、垃圾回收器
2.1 GC 对比
| GC | 说明 | 适用场景 |
|---|---|---|
| Serial | 单线程 | 客户端 |
| Parallel | 多线程 | 吞吐优先 |
| CMS | 并发标记清除 | 低延迟 |
| G1 | 分区收集 | 大堆、低延迟 |
| ZGC | 并发整理 | 超大堆、极低延迟 |
2.2 G1 配置示例
bash
# G1 GC 配置
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:G1HeapRegionSize=16m
-XX:InitiatingHeapOccupancyPercent=45
-XX:G1ReservePercent=10
2.3 ZGC 配置示例
bash
# ZGC 配置 (JDK 15+)
-XX:+UseZGC
-XX:ZCollectionInterval=5
-XX:ZAllocationSpikeTolerance=5
-XX:+UnlockDiagnosticVMOptions
-XX:+ZProactive
JVM 垃圾回收器(GC)对比与选型图:

三、调优主要参数
3.1 内存配置
bash
# 推荐配置
-Xms4g # 初始堆 = 最大堆
-Xmx4g # 避免动态扩容
-Xmn2g # 新生代 = 堆的 50%
-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=512m
-XX:+UseCompressedOops # 压缩指针
-XX:+UseCompressedClassPointers
3.2 GC 配置
bash
# G1 GC 完整配置
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:G1HeapRegionSize=16m
-XX:InitiatingHeapOccupancyPercent=45
-XX:G1ReservePercent=10
-XX:G1NewSizePercent=5
-XX:G1MaxNewSizePercent=60
-XX:G1HeapWastePercent=5
-XX:G1MixedGCCountTarget=8
-XX:G1MixedGCLiveThresholdPercent=85
3.3 日志配置
bash
# GC 日志 (JDK 11+)
-Xlog:gc*:file=gc.log:time,level,tags:filecount=5,filesize=10m
四、问题诊断
4.1 常用工具
| 工具 | 说明 |
|---|---|
| jstat | GC 统计 |
| jmap | 内存映射 |
| jstack | 线程栈 |
| jinfo | JVM 信息 |
| VisualVM | 可视化分析 |
| Arthas | 在线诊断 |
4.2 OOM 排查
bash
# 导出堆转储
jmap -dump:format=b,file=heap.hprof <pid>
# 分析堆转储
# 使用 MAT 或 VisualVM 分析
4.3 CPU 飙高排查
bash
# 查看线程 CPU 使用
top -H -p <pid>
# 导出线程栈
jstack <pid> > thread.log
# 找到高 CPU 线程对应的堆栈
# 线程 ID 转 16 进制
printf "%x\n" <thread_id>
五、实战案例
Linux 下 JVM 调优标准流程图:

5.1 案例:Full GC 频繁
问题现象:系统每隔几分钟 Full GC
分析步骤:
1. jstat -gcutil <pid> 1000
2. 发现老年代增长快
3. jmap -histo <pid> 查看对象分布
4. 发现大量大对象
解决方案:
1. 增大堆内存
2. 调整新生代比例
3. 优化代码减少大对象
5.2 案例:内存泄漏
问题现象:老年代持续增长,Full GC 无法回收
分析步骤:
1. jmap -dump 导出堆转储
2. MAT 分析 Dominator Tree
3. 找到占用最大的对象
4. 查看 GC Roots
解决方案:
1. 修复代码中的泄漏点
2. 使用 WeakReference 替代强引用
总结
✅ JVM 内存模型 :堆、栈、方法区
✅ 垃圾回收器 :G1、ZGC
✅ 调优参数 :内存、GC、日志
✅ 问题诊断 :OOM、CPU 飙高
✅ 实战案例:Full GC、内存泄漏
作者 :刘~浪地球
更新时间:2026-04-15