启动参数调优

返回 Java 基础

JVM 启动参数决定了内存布局、GC 行为、JIT 编译策略和诊断能力。本文系统整理生产常用参数,并给出典型场景的配置模板。


参数类型速查

前缀含义示例
-标准参数,所有 JVM 支持-version, -cp
-X非标准参数,HotSpot 专有但常用-Xms, -Xmx, -Xss
-XX:不稳定参数,调优核心,分 boolean 和 kv 两类-XX:+UseG1GC, -XX:MaxGCPauseMillis=200
-D设置系统属性(System.getProperty-Dfile.encoding=UTF-8
-XX:+FlagName    # 开启布尔参数
-XX:-FlagName    # 关闭布尔参数
-XX:Key=Value    # 键值参数

内存相关参数

堆内存

-Xms2g                         # 初始堆大小(建议与 Xmx 相同,避免动态扩缩开销)
-Xmx2g                         # 最大堆大小
 
# 新生代
-Xmn512m                       # 新生代固定大小(与 NewRatio 二选一)
-XX:NewRatio=2                  # 老年代:新生代 = 2:1(默认),即新生代占 1/3
-XX:SurvivorRatio=8             # Eden:Survivor = 8:1:1(默认)
 
# 大对象直接进老年代阈值(G1 下单独用 G1HeapRegionSize 控制)
-XX:PretenureSizeThreshold=1m
 
# 对象晋升老年代的年龄阈值(默认 15)
-XX:MaxTenuringThreshold=15

栈内存

-Xss512k          # 每个线程的栈大小(默认 512k~1m,线程多时可适当减小)
                  # 递归深度大的程序需增大,如 -Xss2m

元空间(Metaspace)

-XX:MetaspaceSize=256m          # 初始元空间大小(也是首次扩容触发 Full GC 的阈值)
-XX:MaxMetaspaceSize=512m       # 最大元空间(不设则受限于系统内存)
-XX:MinMetaspaceFreeRatio=40    # GC 后元空间空闲率低于此值则扩容
-XX:MaxMetaspaceFreeRatio=70    # GC 后元空间空闲率高于此值则缩容

动态代理、JSP、OSGi 等场景类加载频繁,需监控元空间使用量。

直接内存(堆外)

-XX:MaxDirectMemorySize=512m    # NIO DirectBuffer、Netty 堆外内存上限
                                # 默认等于 -Xmx,不显式设置可能被忽略

垃圾收集器参数

选择收集器

-XX:+UseSerialGC                # Serial + Serial Old,单核小内存
-XX:+UseParallelGC              # Parallel Scavenge + Parallel Old,吞吐量优先(JDK 8 默认)
-XX:+UseG1GC                    # G1,JDK 9+ 默认,延迟与吞吐量均衡
-XX:+UseZGC                     # ZGC,JDK 15+ 生产可用,停顿 < 1ms
-XX:+UseShenandoahGC            # Shenandoah,OpenJDK 包含,停顿目标与 ZGC 类似

G1 调优参数

-XX:+UseG1GC
-XX:MaxGCPauseMillis=200        # 停顿时间目标(ms),G1 会据此调整回收范围,默认 200
-XX:G1HeapRegionSize=4m         # Region 大小(1~32m,必须是 2 的幂),建议堆 / 2048
-XX:G1NewSizePercent=5          # 新生代最小占比(默认 5%)
-XX:G1MaxNewSizePercent=60      # 新生代最大占比(默认 60%)
-XX:G1ReservePercent=10         # 保留堆比例作为晋升缓冲(默认 10%)
-XX:InitiatingHeapOccupancyPercent=45   # 老年代占整堆比例达到此值触发并发标记(默认 45%)
-XX:G1MixedGCCountTarget=8      # Mixed GC 最多分几次完成(默认 8)
-XX:ConcGCThreads=4             # 并发标记线程数(默认 CPU/4)
-XX:ParallelGCThreads=8         # STW 阶段并行线程数(默认 CPU 数或受限值)

ZGC 调优参数

-XX:+UseZGC
-XX:ZCollectionInterval=0       # 主动 GC 间隔(秒),0 = 禁用(默认),生产可设 5~30
-XX:ZAllocationSpikeTolerance=2 # 分配速率突增容忍系数(默认 2),内存不稳时增大
-XX:ZUncommitDelay=300          # 将未使用内存归还 OS 的延迟(秒,默认 300)
-XX:SoftMaxHeapSize=1800m       # 软上限,ZGC 尽量不超过此值(配合 -Xmx 使用)

JDK 21+ ZGC 支持分代(-XX:+ZGenerational),可显著降低短生命周期对象的 GC 开销。

GC 日志(JDK 9+ 统一日志)

-Xlog:gc*:file=/var/log/app/gc.log:time,uptime,level,tags:filecount=10,filesize=20m
# gc*         :输出所有 gc 相关日志标签
# time        :绝对时间
# uptime      :JVM 启动后时间
# filecount=10:滚动保留 10 个文件
# filesize=20m:每文件 20MB
 
# 仅看 GC 停顿摘要
-Xlog:gc:stdout:time,uptime

JIT 编译参数

# 分层编译(JDK 8+ 默认开启)
-XX:+TieredCompilation
 
# JIT 编译阈值(方法调用次数,默认 10000)
-XX:CompileThreshold=10000
 
# 禁用 C2(仅用 C1,适合启动速度敏感场景)
-XX:TieredStopAtLevel=1
 
# 内联控制
-XX:MaxInlineSize=35            # 可内联方法的最大字节码大小(默认 35)
-XX:FreqInlineSize=325          # 频繁调用方法的内联大小上限(默认 325)
-XX:InlineSmallCode=1000        # 已编译方法可被内联的最大机器码大小
 
# 逃逸分析(默认开启,JDK 8+)
-XX:+DoEscapeAnalysis
 
# Code Cache 大小(JIT 编译后的机器码存放区)
-XX:ReservedCodeCacheSize=256m  # 默认 240m(JDK 8),不足时 JIT 降速
-XX:InitialCodeCacheSize=64m

线程与并发参数

# 虚拟线程(JDK 21+)
# 无需额外 JVM 参数,直接用 Thread.ofVirtual() 或 Executors.newVirtualThreadPerTaskExecutor()
 
# ForkJoinPool 公共池并行度(影响 Stream 并行、CompletableFuture)
-Djava.util.concurrent.ForkJoinPool.common.parallelism=8
 
# 偏向锁(JDK 15 废弃,JDK 18 移除;锁升级见 [[JUC#锁升级lock-escalation|锁升级(Lock Escalation)]])
-XX:-UseBiasedLocking           # JDK 8~14:高竞争场景关闭偏向锁,减少撤销 STW 开销

诊断与监控参数

# OOM 时自动 dump 堆快照
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/var/log/app/heapdump.hprof
 
# OOM 时执行脚本(发告警)
-XX:OnOutOfMemoryError="kill -9 %p; /scripts/alert.sh"
 
# 启动时打印所有 JVM 参数(含默认值)
-XX:+PrintFlagsFinal
 
# 打印命令行参数
-XX:+PrintCommandLineFlags
 
# 开启 JMX 远程监控(配合 jconsole / VisualVM)
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9010
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
 
# 开启 JFR(Java Flight Recorder,JDK 11+,生产可用)
-XX:+FlightRecorder
-XX:StartFlightRecording=duration=60s,filename=/tmp/app.jfr

常见系统属性

-Dfile.encoding=UTF-8                      # 文件默认编码
-Duser.timezone=Asia/Shanghai              # 时区
-Djava.io.tmpdir=/data/tmp                 # 临时目录
-Dspring.profiles.active=prod              # Spring 激活 Profile
-Dserver.port=8080                         # Spring Boot 端口
-Dlogging.level.root=INFO                  # Spring 日志级别

容器(Docker / K8s)注意事项

JDK 8u191 / JDK 10+ 起自动感知容器 CPU 和内存限制:

# 开启容器感知(JDK 8u191~8u311 需显式开启,JDK 11+ 默认开启)
-XX:+UseContainerSupport
 
# 堆占容器内存的比例(默认 25%,生产建议 75%~80%)
-XX:MaxRAMPercentage=75.0
-XX:InitialRAMPercentage=50.0
-XX:MinRAMPercentage=50.0
 
# 使用绝对值时(容器内存已知且固定)
-Xms512m -Xmx512m

不要在容器里用 -Xmx 设超出容器内存限制的值,会被 OOMKilled。
推荐用 MaxRAMPercentage 替代绝对值,更适应弹性调度。

ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 \
               -XX:+UseZGC \
               -XX:+HeapDumpOnOutOfMemoryError \
               -XX:HeapDumpPath=/tmp/heapdump.hprof \
               -Xlog:gc*:file=/var/log/gc.log:time,uptime:filecount=5,filesize=10m"
 
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

场景配置模板

Web 服务(低延迟优先,G1)

java \
  -Xms2g -Xmx2g \
  -XX:+UseG1GC \
  -XX:MaxGCPauseMillis=100 \
  -XX:G1HeapRegionSize=4m \
  -XX:InitiatingHeapOccupancyPercent=40 \
  -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m \
  -XX:MaxDirectMemorySize=256m \
  -Xss512k \
  -XX:+HeapDumpOnOutOfMemoryError \
  -XX:HeapDumpPath=/var/log/heapdump.hprof \
  -Xlog:gc*:file=/var/log/gc.log:time,uptime:filecount=10,filesize=20m \
  -Dfile.encoding=UTF-8 \
  -Duser.timezone=Asia/Shanghai \
  -jar app.jar

超低延迟服务(ZGC,JDK 21)

java \
  -Xms4g -Xmx4g \
  -XX:+UseZGC \
  -XX:+ZGenerational \
  -XX:SoftMaxHeapSize=3500m \
  -XX:ZCollectionInterval=10 \
  -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m \
  -XX:+HeapDumpOnOutOfMemoryError \
  -Xlog:gc*:file=/var/log/gc.log:time,uptime:filecount=5,filesize=10m \
  -jar app.jar

批处理 / 大吞吐量(Parallel GC)

java \
  -Xms4g -Xmx8g \
  -XX:+UseParallelGC \
  -XX:ParallelGCThreads=8 \
  -XX:GCTimeRatio=19 \
  -XX:MaxGCPauseMillis=500 \
  -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m \
  -XX:+HeapDumpOnOutOfMemoryError \
  -jar app.jar

容器化应用(K8s,内存 2Gi 限制)

java \
  -XX:+UseContainerSupport \
  -XX:MaxRAMPercentage=75.0 \
  -XX:InitialRAMPercentage=50.0 \
  -XX:+UseG1GC \
  -XX:MaxGCPauseMillis=200 \
  -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m \
  -XX:+HeapDumpOnOutOfMemoryError \
  -XX:HeapDumpPath=/tmp/heapdump.hprof \
  -Xlog:gc:stdout:time,uptime \
  -jar app.jar

调优流程

1. 明确目标:吞吐量?延迟(P99/P999)?内存占用?
       ↓
2. 收集基线数据
   - GC 日志(停顿频率、停顿时长、每次回收量)
   - jcmd <pid> VM.flags       # 当前生效参数
   - jcmd <pid> GC.heap_info   # 堆区使用情况
       ↓
3. 选择收集器
   - 吞吐量优先 → Parallel GC
   - 延迟优先(< 200ms) → G1
   - 超低延迟(< 10ms) → ZGC / Shenandoah
       ↓
4. 调整内存分配
   - Xms = Xmx(避免动态扩缩)
   - 新生代大小影响 Minor GC 频率和 Full GC 触发
   - 元空间防止频繁 Full GC
       ↓
5. 验证效果
   - GCEasy / GCViewer 分析 GC 日志
   - JFR 录制分析热点与内存分配
   - 压测对比 P99 延迟和 TPS

相关

  • JVM — JVM 内存结构与收集器原理
  • 垃圾回收 — GC 算法与收集器详解
  • JIT — JIT 编译器工作原理
  • jcmd — 运行时查询和操控 JVM 的首选工具
  • jstack — 线程栈诊断
  • Spring Boot 性能调优 — 应用层调优配合 JVM 参数