启动参数调优
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,uptimeJIT 编译参数
# 分层编译(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