Skip to content

内存/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.jar

GC 参数设置

GC 选择决策树

GC 选择决策树:

你的应用场景是什么?

├── 桌面应用 / 小内存(< 100MB)
│      └── Serial GC(-XX:+UseSerialGC)

├── 中小型服务端应用
│      │
│      ├── 追求低延迟(P99 < 100ms)
│      │      └── G1 GC(-XX:+UseG1GC)
│      │
│      └── 追求高吞吐量
│             └── Parallel GC(-XX:+UseParallelGC)

└── 大内存应用(> 8GB)/ 追求极致低延迟
       └── ZGC(-XX:+UseZGC)或 Shenandoah

Serial GC(最简单)

适用于单线程、小内存场景:

bash
java -Xms256m -Xmx256m \
     -XX:+UseSerialGC \
     -jar myapp.jar

Parallel 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 → 单文件最大 100MB

JDK 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.log

GC 日志关键指标

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 参数

基于 VitePress 构建