内存/GC/日志相关参数设置
调优实战:参数设置指南
上一节梳理了 JVM 参数的分类,这一节聚焦于最常用的内存、GC 和日志相关的参数设置。
内存参数设置
堆内存设置原则
堆内存设置的核心原则:
1. 不要设置过大
- 过大的堆会导致 GC 时间过长
- G1/ ZGC 建议不超过 8GB
- 大堆用 ZGC 或分片方案
2. Xms 和 Xmx 设置相同
- 避免运行时调整堆大小带来的开销
- 生产环境必须设置
3. 留足够内存给操作系统
- 建议 OS 保留 1~2GB
- 容器环境留 10%~25% 给 OS通用推荐配置
bash
# 小型应用(< 2GB 堆)
java -Xms512m -Xmx512m \
-XX:MetaspaceSize=128m \
-XX:MaxMetaspaceSize=256m \
-jar myapp.jar
# 中型应用(2~4GB 堆)
java -Xms2g -Xmx2g \
-XX:MetaspaceSize=256m \
-XX:MaxMetaspaceSize=512m \
-jar myapp.jar
# 大型应用(> 4GB 堆,推荐 G1 或 ZGC)
java -Xms4g -Xmx4g \
-XX:MetaspaceSize=512m \
-XX:MaxMetaspaceSize=1g \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-jar myapp.jar容器环境内存设置
bash
# JDK 10+ 推荐使用百分比方式
java -XX:+UseContainerSupport \
-XX:MaxRAMPercentage=75.0 \
-XX:InitialRAMPercentage=75.0 \
-XX:+UseG1GC \
-jar myapp.jar
# 容器内存 4GB,JVM 最多使用 3GB
# 容器内存 8GB,JVM 最多使用 6GB年轻代设置
bash
# 固定年轻代大小(推荐)
java -Xms4g -Xmx4g \
-Xmn2g \
-jar myapp.jar
# 使用比例(不推荐,难以精确控制)
java -Xms4g -Xmx4g \
-XX:NewRatio=2 \
-jar myapp.jarGC 参数设置
GC 选择决策树
GC 选择决策树:
你的应用场景是什么?
├── 桌面应用 / 小内存(< 100MB)
│ └── Serial GC(-XX:+UseSerialGC)
│
├── 中小型服务端应用
│ │
│ ├── 追求低延迟(P99 < 100ms)
│ │ └── G1 GC(-XX:+UseG1GC)
│ │
│ └── 追求高吞吐量
│ └── Parallel GC(-XX:+UseParallelGC)
│
└── 大内存应用(> 8GB)/ 追求极致低延迟
└── ZGC(-XX:+UseZGC)或 ShenandoahSerial GC(最简单)
适用于单线程、小内存场景:
bash
java -Xms256m -Xmx256m \
-XX:+UseSerialGC \
-jar myapp.jarParallel GC(高吞吐量)
适用于批处理、数据计算等吞吐量优先的场景:
bash
java -Xms4g -Xmx4g \
-XX:+UseParallelGC \
-XX:ParallelGCThreads=8 \
-XX:+UseAdaptiveSizePolicy \
-XX:MaxGCPauseMillis=500 \
-jar myapp.jar
# 参数说明:
# -XX:ParallelGCThreads → GC 线程数,默认 = CPU 核数
# -XX:+UseAdaptiveSizePolicy → 自动调整各代大小
# -XX:MaxGCPauseMillis → 最大停顿目标(软目标,不保证)G1 GC(均衡,推荐)
适用于大多数服务端应用,是 JDK 9+ 的默认 GC:
bash
java -Xms4g -Xmx4g \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-XX:G1HeapRegionSize=4m \
-XX:InitiatingHeapOccupancyPercent=45 \
-jar myapp.jar
# 参数说明:
# -XX:MaxGCPauseMillis → 最大停顿目标(G1 会尽量满足)
# -XX:G1HeapRegionSize → Region 大小(1MB~32MB,自动计算时由堆大小决定)
# -XX:InitiatingHeapOccupancyPercent → 老年代占比超过多少时触发并发标记(默认 45%)ZGC(极低延迟)
适用于大内存、极低延迟要求的场景:
bash
java -Xms8g -Xmx8g \
-XX:+UseZGC \
-XX:+ZGenerational \
-XX:MaxHeapSize=8g \
-jar myapp.jar
# ZGC 特点:
# ✓ 停顿时间 < 1ms
# ✓停顿时间不随堆增大而增长
# ✓ 支持 TLAB 分配
# ✗ JDK 15 前不支持分代(已支持)
# ✗ 吞吐量略低于 G1各 GC 参数对比
| GC | 停顿时间 | 吞吐量 | 内存 | 适用场景 |
|---|---|---|---|---|
| Serial | 长(Stop the World) | 中 | 小(百 MB~GB) | 单线程、批处理 |
| Parallel | 较长 | 高 | 大 | 吞吐量优先 |
| CMS | 较短(并发) | 高 | 中大 | 低延迟(已废弃) |
| G1 | 可控(软目标) | 高 | 大(GB~TB) | 通用,推荐 |
| ZGC | < 1ms | 中高 | 超大(TB) | 极致低延迟 |
| Shenandoah | < 1ms | 中高 | 大 | 低延迟(OpenJDK) |
GC 日志参数设置
JDK 9+ 的新日志系统(统一日志)
JDK 9+ 使用 -Xlog 统一日志系统:
-Xlog 的格式:
-Xlog:[<selectors>][:[<output>][:[<decorators>][:[<options>]]]]
selectors → 日志选择器(哪些日志)
output → 输出目标
decorators → 装饰器(时间、级别等)
options → 其他选项基本用法
bash
# 开启所有 GC 日志
-Xlog:gc*:file=/var/log/myapp/gc.log
# 等价于 JDK 8 的:
# -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/var/log/myapp/gc.log选择器(Selectors)
bash
# 只记录 GC 日志
-Xlog:gc:file=gc.log
# 记录所有 GC 日志(含标签)
-Xlog:gc*:file=gc_all.log
# 记录 GC 和堆信息
-Xlog:gc,heap*:file=gc_heap.log
# 记录 GC 和类加载
-Xlog:gc,class+load:file=gc_class.log
# 标签列表:
# gc → GC 基本信息
# gc* → 所有 GC 相关
# metaspace → 元空间
# print → GC 日志详情
# exit → JVM 退出时的 GC 统计装饰器(Decorators)
bash
# 常用装饰器组合
-Xlog:gc*:file=gc.log:time,uptime,level,tags
# 装饰器说明:
# time → 绝对时间(2026-03-22T10:00:00.123+0800)
# uptime → JVM 启动后的相对时间
# level → 日志级别(INFO/WARNING/ERROR)
# tags → 日志标签
# pid → 进程 ID
# tid → 线程 ID
# nanos → 纳秒时间戳输出选项
bash
# 输出到文件
-Xlog:gc*:file=gc.log
# 输出到 stdout
-Xlog:gc*:stdout
# 输出到 stderr
-Xlog:gc*:stderr
# 文件滚动
-Xlog:gc*:file=/path/to/gc.log:filecount=5,filesize=10M
# 参数说明:
# filecount → 保留文件数量(默认 0,不滚动)
# filesize → 单个文件大小,超过则滚动完整示例
bash
java -Xms4g -Xmx4g \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-Xlog:gc*:file=/var/log/myapp/gc_%t.log:time,uptime,level,tags,filecount=10,filesize=100M \
-jar myapp.jar
# 说明:
# gc* → 所有 GC 相关日志
# file → 输出到文件
# %t → 时间戳占位符(避免文件名冲突)
# filecount=10 → 保留 10 个文件
# filesize=100M → 单文件最大 100MBJDK 8 及之前的 GC 日志
如果还在用 JDK 8:
bash
java -Xms4g -Xmx4g \
-XX:+UseG1GC \
-XX:+PrintGCDetails \
-XX:+PrintGCDateStamps \
-XX:+PrintTenuringDistribution \
-XX:+PrintGCApplicationStoppedTime \
-Xloggc:/var/log/myapp/gc.log \
-jar myapp.jar
# 参数说明:
# -XX:+PrintGCDetails → 详细 GC 日志
# -XX:+PrintGCDateStamps → 打印日期时间戳
# -XX:+PrintTenuringDistribution → 对象晋升信息
# -XX:+PrintGCApplicationStoppedTime → 打印 GC 停顿时间日志分析与可视化
GC 日志分析工具
bash
# GCEasy(在线 + 离线)
# https://gceasy.io/
# 支持上传 gc.log,自动分析并生成报告
# GCViewer(开源)
# https://github.com/chewiebug/GCViewer
java -jar gcviewer.jar gc.log
# 对比两个 GC 日志
java -jar gcviewer.jar gc_before.log gc_after.logGC 日志关键指标
GCViewer/GCEasy 报告的关键指标:
1. Throughput(吞吐量)
→ 理想值:> 95%
→ 计算:GC 时间占比
2. GC Pause(GC 停顿)
→ Minor GC 停顿时间
→ Full GC 停顿时间
3. Freed Memory(回收内存)
→ 每次 GC 回收了多少内存
4. Allocation Rate(分配速率)
→ 对象分配速率(MB/s)
→ 高分配速率需要更多 GC
5. Promotion Rate(晋升速率)
→ 对象晋升到老年代的速率
→ 高晋升速率说明年轻代太小OOM 参数设置
bash
java -Xms4g -Xmx4g \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/var/log/myapp/oom \
-XX:+ExitOnOutOfMemoryError \
-jar myapp.jar
# 参数说明:
# -XX:+HeapDumpOnOutOfMemoryError → OOM 时自动生成堆转储
# -XX:HeapDumpPath → 堆转储文件保存路径
# -XX:+ExitOnOutOfMemoryError → OOM 时直接退出(可选,避免进程处于不稳定状态)生产环境推荐配置
Web 服务(追求低延迟)
bash
java -Xms2g -Xmx2g \
-XX:MetaspaceSize=256m \
-XX:MaxMetaspaceSize=512m \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=100 \
-XX:+ParallelRefProcEnabled \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/var/log/myapp \
-Xlog:gc*:file=/var/log/myapp/gc.log:time,uptime,level,tags,filecount=5,filesize=50M \
-jar myapp.jar数据处理(追求高吞吐)
bash
java -Xms8g -Xmx8g \
-XX:MetaspaceSize=512m \
-XX:MaxMetaspaceSize=1g \
-XX:+UseParallelGC \
-XX:ParallelGCThreads=16 \
-XX:+UseAdaptiveSizePolicy \
-XX:MaxGCPauseMillis=500 \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/var/log/myapp \
-Xlog:gc:/var/log/myapp/gc.log:time,uptime \
-jar myapp.jar容器环境(JDK 11+)
bash
java -XX:+UseContainerSupport \
-XX:MaxRAMPercentage=75.0 \
-XX:InitialRAMPercentage=75.0 \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/var/log/myapp \
-Xlog:gc*:file=/var/log/myapp/gc.log:time,uptime,level,tags,filecount=3,filesize=100M \
-jar myapp.jar本节小结
内存/GC/日志参数速查:
| 类别 | 核心参数 | 说明 |
|---|---|---|
| 堆大小 | -Xms、-Xmx | 建议相同,避免运行时调整 |
| 年轻代 | -Xmn、-XX:NewRatio | 固定大小优于比例 |
| GC 选择 | -XX:+UseG1GC 等 | 根据场景选择 |
| G1 调优 | MaxGCPauseMillis | 软目标,不保证 |
| GC 日志 | -Xlog:gc* | JDK 9+ 统一日志系统 |
| OOM 处理 | -XX:+HeapDumpOnOutOfMemoryError | 自动保存堆转储 |
调优顺序:先选对 GC → 设置合理的堆大小 → 开启 GC 日志 → 观察分析 → 针对性调优。
下一节,我们来看 Java 代码获取 JVM 参数。
