Striveonger

vuePress-theme-reco Mr.Lee    2015 - 2026
Striveonger Striveonger
主页
分类
  • 笔记
  • 文章
  • 工具
  • 读书/工具
标签
时间轴
简历
author-avatar

Mr.Lee

274

Article

145

Tag

主页
分类
  • 笔记
  • 文章
  • 工具
  • 读书/工具
标签
时间轴
简历

JVM 调优参数详解:从理论到实践

vuePress-theme-reco Mr.Lee    2015 - 2026

JVM 调优参数详解:从理论到实践

Mr.Lee 2026-04-14 10:30:00 JVMGCG1

本文档基于 Docker 容器化部署的 Java 17 应用的 JVM 调优参数进行分析,涵盖内存配置、GC 配置、调试诊断和优化选项等内容。

# 环境信息

  • JDK 版本: 17
  • 垃圾收集器: G1 GC
  • 容器资源: 4 CPU, 8GB 内存
  • 部署方式: Docker 容器化部署

# 一、内存配置参数

参数 值 说明
-XX:InitialRAMPercentage 75.0 初始堆内存占容器内存的 75%
-XX:MaxRAMPercentage 75.0 最大堆内存占容器内存的 75%
-XX:MetaspaceSize 512m 元空间初始大小
-XX:MaxMetaspaceSize 512m 元空间最大大小(防止元空间膨胀)

# 1.1 堆内存配置策略

采用容器感知方式配置堆内存:

InitialRAMPercentage / MaxRAMPercentage: JDK 10+ 支持的参数. 以容器可用内存的百分比形式设置堆大小, 这种方式比传统的 -Xms/-Xmx 更适合容器化环境, 可自动适应不同容量的宿主机.

堆内存大小 = 容器内存 × 75% = 8GB × 75% = 6GB
1

# 1.2 元空间配置

  • MetaspaceSize:控制 Metaspace 的初始大小
  • MaxMetaspaceSize:限制 Metaspace 的最大增长,防止元空间无限膨胀导致容器 OOM
  • 元空间存储内容:类的元数据、方法信息、JIT 编译后的代码等

# 二、GC 配置参数

参数 说明
-XX:+UseG1GC 使用 G1 垃圾收集器
-XX:MaxGCPauseMillis=200 GC 最大停顿时间目标 200ms

# 2.1 G1 GC 特点

G1(Garbage-First)收集器是 JDK 9+ 的默认垃圾收集器,具有以下特点:

  • 分代收集:仍然保留新生代和老年代的概念,但采用分区(Region)方式管理
  • 可预测停顿:通过 -XX:MaxGCPauseMillis 可以指定停顿时间目标
  • 吞吐量与延迟平衡:适合对延迟有要求的应用

# 2.2 停顿时间目标

-XX:MaxGCPauseMillis=200 表示 GC 停顿时间目标为 200ms,但这是一个软目标,G1 会尽可能接近但不能保证严格遵守。


# 三、调试与诊断参数

参数 说明
-XX:+HeapDumpOnOutOfMemoryError OOM 时自动生成堆转储文件
-XX:HeapDumpPath=/logs/heapdump.hprof 堆转储文件保存路径
-XX:+ExitOnOutOfMemoryError OOM 时直接退出进程,不尝试继续运行
-Xlog:gc*:file=/logs/gc.log:time,uptime,level,tags:filecount=5,filesize=50m GC 日志配置

# 3.1 堆转储配置

堆转储(Heap Dump)是排查内存问题的重要工具:

  • HeapDumpOnOutOfMemoryError:在 OOM 发生前,JVM 会自动生成 .hprof 文件
  • HeapDumpPath:指定转储文件的保存位置
  • 生成的 heapdump.hprof 文件可通过 MAT(Memory Analyzer Tool)、JProfiler 等工具分析

# 3.2 ExitOnOutOfMemoryError

启用此参数后,JVM 遇到 OOM 会直接退出进程。在容器环境中推荐启用,原因:

  • 避免 OOM 后应用处于不可预测状态
  • 配合容器健康检查,快速重启恢复服务
  • 配合 restart=always,实现故障自动恢复

# 四、GC 日志详解

# 4.1 -Xlog:gc* 统一日志框架

JDK 9+ 引入了统一的 JVM 日志框架,替代了之前零散的 GC 日志参数。

# 语法结构

-Xlog:选择器:输出目标:滚动策略:输出格式
1

# 参数拆解

-Xlog:gc*:file=/logs/gc.log:time,uptime,level,tags:filecount=5,filesize=50m
   │    │                    │                  │                        │
   │    │                    │                  │                        └─ 滚动策略
   │    │                    │                  └─ 输出格式
   │    │                    └─ 输出文件路径
   │    └─ 日志选择器
   └─ 日志级别(默认 INFO)
1
2
3
4
5
6
7

# 4.2 日志选择器

模式 含义
gc 仅 gc 标签
gc* 所有以 gc 开头的标签(最常用)
gc,class 同时包含 gc 和 class 加载日志
gc*=debug gc* 且日志级别为 debug

# 4.3 输出格式

格式符 输出示例
time 2026-04-13T10:30:15.123+0800
uptime 5.123s(JVM 启动以来的秒数)
level info、debug、warn、error
tags [GC,AllocationFailure] 等标签
message 实际日志内容

# 4.4 滚动策略

参数 含义
filecount=5 最多保留 5 个日志文件
filesize=50m 单个文件达到 50MB 时滚动

滚动后文件名:gc.log.0、gc.log.1 ... gc.log.4

# 4.5 输出示例

[2026-04-13T10:30:15.123+0800][5.123s][info][gc,start] GC(0) Pause Young (Normal)
[2026-04-13T10:30:15.456+0800][5.456s][info][gc,heap] GC(0) Eden: 100MB->0MB(200MB)
[2026-04-13T10:30:15.789+0800][5.789s][info][gc,phases,end] GC(0) 666.123ms
1
2
3

# 4.6 旧参数对照表

旧参数(JDK 8) 新参数(JDK 9+)
-XX:+PrintGC -Xlog:gc*
-XX:+PrintGCDetails -Xlog:gc*=debug
-XX:+PrintGCDateStamps time
-XX:PrintGCApplicationStoppedTime -Xlog:safepoint

# 4.7 常用配置参考

# 生产环境:输出到文件,滚动保留
-Xlog:gc*:file=/logs/gc.log:time,uptime,level,tags:filecount=10,filesize=100m

# 开发环境:同时输出到控制台
-Xlog:gc*:stdout:time,uptime,level,tags:message

# 详细模式:包含分阶段信息
-Xlog:gc*=debug,phases:file=/logs/gc-detail.log:time,uptime,level,tags:filecount=5,filesize=100m
1
2
3
4
5
6
7
8

# 五、其他优化参数

参数 说明
-XX:+UseStringDeduplication 字符串去重,节省内存(对大量重复字符串场景有效)
-XX:+AlwaysPreTouch 启动时预分配内存页,避免运行时分配延迟
-Dfile.encoding=UTF-8 设置文件编码为 UTF-8
-Dprofile=dev 指定 Spring Boot 激活的 profile

# 5.1 UseStringDeduplication

启用后,G1 会将相同的字符串实例合并共享,只保留一份实际存储,可显著降低内存占用。适用于:

  • 大量重复字符串的场景(如 JSON 响应、数据库字段值)
  • 内存敏感型应用

# 5.2 AlwaysPreTouch

将堆内存和元空间在 JVM 启动时一次性映射到物理内存,避免运行时第一次访问时的页错误延迟。代价是启动时间会稍有增加。


# 六、完整启动脚本参考

JAVA_OPTS=" \
-XX:InitialRAMPercentage=75.0 \
-XX:MaxRAMPercentage=75.0 \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/logs/heapdump.hprof \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-XX:+UseStringDeduplication \
-XX:+AlwaysPreTouch \
-XX:+ExitOnOutOfMemoryError \
-XX:MetaspaceSize=512m \
-XX:MaxMetaspaceSize=512m \
-Xlog:gc*:file=/logs/gc.log:time,uptime,level,tags:filecount=5,filesize=50m \
-Dlogging.file.path=/logs \
-Dfile.encoding=UTF-8 \
-Dprofile=dev"

docker run \
       --name=java \
       --cpus=4 \
       --memory=8g \
       -p 8880:8080 \
       --restart=always \
       bellsoft/liberica-openjdk-debian:17.0.11-cds \
       sh -c "java \$JAVA_OPTS -jar /java/ruoyi-admin.jar"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 七、JVM 调优学习路线

# 7.1 基础知识

  1. 堆内存结构:新生代(Eden、Survivor)、老年代、Metaspace
  2. GC 四大算法:标记-清除、标记-整理、复制、增量更新
  3. 对象晋升机制:对象年龄阈值、动态年龄判断

# 7.2 垃圾收集器

收集器 特点 适用场景
Serial 单线程,适合小内存 客户端、极少量内存
Parallel 吞吐量优先 后台批处理
CMS 并发收集、低停顿 对延迟敏感的应用
G1 分区式、可预测停顿 JDK 9+ 默认,通用场景
ZGC 低延迟(亚毫秒级) 超大堆内存(TB 级)
Shenandoah 低延迟,GC 与应用并发 对延迟极度敏感

# 7.3 诊断工具

工具 用途
jstat -gcutil <pid> 1000 实时监控 GC 统计信息
jmap -heap <pid> 查看堆内存布局
jmap -dump:file=heap.hprof <pid> 手动生成堆转储
jstack <pid> 查看线程堆栈信息
Arthas 阿里开源诊断工具,功能全面
GCViewer 分析 GC 日志文件
MAT / JProfiler 堆转储文件分析

# 7.4 调优思路

  1. 确定目标:吞吐量优先还是延迟优先?
  2. 收集数据:开启 GC 日志,运行压测
  3. 分析日志:GC 频率、停顿时间、内存使用率
  4. 调整参数:从小到大,逐步验证
  5. 监控验证:上线后持续监控,避免退化

# 参考资料

  • JVM 日志官方文档
  • G1 收集器官方文档
  • Java HotSpot VM 选项完整列表