Skip to content
清晨的一缕阳光
返回

JVM 调优实战指南

JVM 调优实战指南

JVM 调优是提升 Java 应用性能的关键,需要理解 JVM 原理和掌握调优工具。

一、JVM 参数配置

1.1 堆内存参数

# 初始堆大小
-Xms2g

# 最大堆大小
-Xmx4g

# 新生代大小
-Xmn1g

# 老年代大小(JDK 8+)
-XX:NewSize=512m
-XX:MaxNewSize=1g

# 堆比例(新生代:老年代)
-XX:NewRatio=2  # 1:2

1.2 栈内存参数

# 线程栈大小
-Xss256k  # 默认 1M,高并发可调小

# 元空间
-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=512m

1.3 GC 参数

# 使用 G1 收集器
-XX:+UseG1GC

# 最大停顿时间
-XX:MaxGCPauseMillis=200

# 并行 GC 线程数
-XX:ParallelGCThreads=8

# 并发 GC 线程数
-XX:ConcGCThreads=2

1.4 日志参数

# JDK 8
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:/var/log/gc.log
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=5
-XX:GCLogFileSize=10M

# JDK 9+
-Xlog:gc*:file=gc.log:time,uptime,level,tags

二、GC 日志分析

2.1 日志解读

# GC 日志示例
2024-01-15T10:30:00.123+0800: 
[GC (Allocation Failure) 
 [PSYoungGen: 256000K->32000K(307200K)]  # 新生代回收
 512000K->288000K(1024000K),             # 堆整体回收
 0.0123456 secs]                          # 耗时

# 字段说明
// 回收前大小->回收后大小 (总容量)
// 堆回收前->堆回收后 (堆总容量)

2.2 关键指标

# 关注指标
- GC 频率:Minor GC 间隔
- GC 耗时:单次 GC 时间
- 晋升速率:新生代→老年代
- 堆使用率:GC 后堆占用

# 正常指标
- Minor GC:< 50ms,每秒 1-2 次
- Full GC:< 1 秒,数分钟一次
- 堆使用率:GC 后 < 50%

2.3 分析工具

# GCViewer(可视化)
java -jar gcviewer.jar gc.log

# GCEasy(在线)
# https://gceasy.io/

# 手动分析
grep "Full GC" gc.log | wc -l  # Full GC 次数
grep "GC" gc.log | awk '{print $NF}' | sort -n | tail  # 最慢 GC

三、问题排查

3.1 内存泄漏

# 症状
- Full GC 频繁
- 堆使用率持续上升
- Old 区只增不减

# 排查步骤
# 1. dump 堆
jmap -dump:format=b,file=heap.hprof <pid>

# 2. MAT 分析
# 打开 heap.hprof,查看 Dominator Tree

# 3. 定位泄漏源
# 查找 GC Roots,分析引用链

3.2 频繁 Full GC

# 原因
1. 老年代空间不足
2. 元空间不足
3. System.gc() 调用
4. dump

# 解决
# 1. 增大堆
-Xmx4g -Xms4g

# 2. 调整新生代
-Xmn2g

# 3. 禁用显式 GC
-XX:+DisableExplicitGC

# 4. 调整晋升阈值
-XX:MaxTenuringThreshold=10

3.3 OOM 问题

# 常见 OOM
1. Java heap space
2. Metaspace
3. GC overhead limit exceeded
4. Out of swap space

# 解决
# 1. 堆空间不足
-Xmx4g

# 2. 元空间不足
-XX:MaxMetaspaceSize=512m

# 3. GC 开销过大
# 优化代码,减少对象创建

# 4. 内存泄漏
# dump 分析

3.4 CPU 过高

# 排查步骤
# 1. 找到高 CPU 进程
top

# 2. 找到高 CPU 线程
top -Hp <pid>

# 3. 转换线程 ID
printf "%x\n" <tid>

# 4. 查看线程栈
jstack <pid> | grep <hex_tid> -A 20

# 5. 定位问题代码
# 死循环、频繁 GC、锁竞争

四、性能优化

4.1 减少对象创建

// ❌ 频繁创建对象
for (int i = 0; i < 10000; i++) {
    StringBuilder sb = new StringBuilder();
    sb.append(i);
}

// ✅ 复用对象
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
    sb.setLength(0);
    sb.append(i);
}

4.2 使用基本类型

// ❌ 包装类型
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
    list.add(i); // 自动装箱
}

// ✅ 基本类型
int[] arr = new int[10000];
for (int i = 0; i < 10000; i++) {
    arr[i] = i;
}

4.3 字符串优化

// ❌ 字符串拼接
String s = "";
for (int i = 0; i < 10000; i++) {
    s += i;
}

// ✅ StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
    sb.append(i);
}
String s = sb.toString();

4.4 集合优化

// ❌ 默认容量,频繁扩容
List<String> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
    list.add(String.valueOf(i));
}

// ✅ 预估容量
List<String> list = new ArrayList<>(10000);
for (int i = 0; i < 10000; i++) {
    list.add(String.valueOf(i));
}

五、监控工具

5.1 命令行工具

# 进程信息
jps -lvm

# 堆信息
jstat -gc <pid> 1000 10

# 线程栈
jstack <pid>

# 堆 dump
jmap -dump:format=b,file=heap.hprof <pid>

# 类信息
jmap -histo <pid> | head -20

5.2 可视化工具

# JDK 自带
jconsole  # 监控
jvisualvm   # 综合分析

# 第三方
MAT       # 内存分析
GCViewer  # GC 日志
Arthas    # 诊断工具

5.3 Arthas 使用

# 启动
java -jar arthas-boot.jar

# 查看线程
thread

# 查看堆
dashboard

# 方法耗时
trace com.example.Service method

# 参数查看
watch com.example.Service method '{params, returnObj}'

六、G1 调优

6.1 G1 参数

# 启用 G1
-XX:+UseG1GC

# 最大停顿时间
-XX:MaxGCPauseMillis=200

# 堆大小(建议固定)
-Xms4g -Xmx4g

# Region 大小(自动计算)
# -XX:G1HeapRegionSize=4m

# 晋升阈值
-XX:MaxTenuringThreshold=10

# 并发线程
-XX:ParallelGCThreads=8
-XX:ConcGCThreads=2

6.2 G1 日志分析

# G1 GC 日志
[GC pause (G1 Evacuation Pause) (young)
, 0.0123456 secs]

# 字段说明
// GC 类型:young / mixed / full
// 耗时:0.0123456 secs

6.3 G1 调优步骤

1. 设置 MaxGCPauseMillis 目标
2. 固定堆大小(-Xms = -Xmx)
3. 监控 GC 日志
4. 调整 Region 大小
5. 调整并发线程数
6. 优化代码减少对象创建

七、最佳实践

7.1 参数配置

# Web 应用(低延迟)
-Xms4g -Xmx4g
-XX:+UseG1GC
-XX:MaxGCPauseMillis=100
-XX:+ParallelRefProcEnabled

# 批处理(高吞吐)
-Xms8g -Xmx8g
-XX:+UseParallelGC
-XX:MaxGCPauseMillis=0
-XX:GCTimeRatio=99

# 高并发
-Xms4g -Xmx4g
-Xss256k
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200

7.2 监控告警

# 监控指标
- 堆使用率 > 80% 告警
- Full GC 间隔 < 5 分钟告警
- GC 耗时 > 1 秒告警
- 线程数 > 阈值告警

# 监控工具
Prometheus + Grafana
ELK(日志分析)
APM(应用性能监控)

八、总结

JVM 调优核心要点:

主题关键参数工具
堆内存-Xms, -Xmx, -Xmnjmap, MAT
GC-XX:+UseG1GC, MaxGCPauseMillisGC 日志,GCViewer
线程-Xssjstack
元空间MetaspaceSizejstat
监控-Xloggcjconsole, Arthas

JVM 调优是系统工程,需要监控→分析→调整→验证的持续迭代。


分享这篇文章到:

上一篇文章
Docker Compose 部署
下一篇文章
MySQL SQL 编写最佳实践