线上系统突然变慢,GC 频繁停顿,甚至 OOM 崩溃——这些问题往往和JVM 参数配置有关。
很多同学对 JVM 参数的印象是「一堆 -XX: 开头的奇怪配置」,不知道从哪里入手。但其实:
- 80% 的场景只需要几个核心参数
- 常见问题可以通过参数调优解决
- 理解参数能帮你快速定位线上问题
这篇帮你把 JVM 参数彻底搞明白。下面我按「内存参数 → GC 参数 → 诊断参数 → 典型模板」的顺序往下聊。
1. 内存参数:堆、栈、元空间 💾
1.1 堆内存参数
# 堆大小-Xms512m# 初始堆大小-Xmx2g# 最大堆大小-Xms和-Xmx设成一样,避免运行时动态扩展# 新生代大小-Xmn256m# 新生代大小(Eden + Survivor)-XX:NewRatio=2# 新生代:老年代 = 1:2(老年代是新生代的 2 倍)# Survivor 区比例-XX:SurvivorRatio=8# Eden:Survivor = 8:1(默认)# 例如:-Xmn512m -XX:SurvivorRatio=8# 则 Eden = 512m * 8/10 = 409.6m# 每个 Survivor = 512m * 1/10 = 51.2m1.2 栈内存参数
# 线程栈大小-Xss1m# 每个线程的栈大小(默认 1MB)-Xss512k# 512KB常见场景:
- 递归调用深:增大
-Xss - 线程数多:减小
-Xss
# 查看默认栈大小java-XX:+PrintFlagsFinal-version|grepThreadStackSize1.3 元空间参数
# Java 8 及之后-XX:MetaspaceSize=256m# 初始元空间大小-XX:MaxMetaspaceSize=512m# 最大元空间大小(默认无限制,受物理内存限制)# Java 7 及之前(永久代)-XX:PermSize=128m# 初始永久代大小-XX:MaxPermSize=256m# 最大永久代大小1.4 直接内存参数
# NIO 直接内存(零拷贝)-XX:MaxDirectMemorySize=1g# 直接内存最大 1GB2. GC 参数:收集器与调优 🧹
2.1 收集器选择
# Serial 收集器(单线程)-XX:+UseSerialGC# ParNew 收集器(多线程新生代)-XX:+UseParNewGC# Parallel 收集器(吞吐量优先)-XX:+UseParallelGC-XX:+UseParallelOldGC# CMS 收集器(低停顿)-XX:+UseConcMarkSweepGC# G1 收集器(可预测停顿)-XX:+UseG1GC# ZGC 收集器(超低停顿)-XX:+UseZGC2.2 CMS 参数
# 启用 CMS-XX:+UseConcMarkSweepGC# 触发阈值-XX:CMSInitiatingOccupancyFraction=80# 老年代使用 80% 时触发 CMS# 启用并发预清理-XX:+UseCMSCompactAtFullCollection# Full GC 时整理碎片-XX:+UseCMSInitiatingOccupancyOnly# 只按设定阈值触发2.3 G1 参数
# 启用 G1-XX:+UseG1GC# 停顿时间目标-XX:MaxGCPauseMillis=200# 目标停顿时间 200ms# Region 大小-XX:G1HeapRegionSize=8m# 每个 Region 大小 8MB# 触发阈值-XX:InitiatingHeapOccupancyPercent=45# 堆使用 45% 时触发并发标记2.4 GC 日志参数
# 打印 GC 详情-XX:+PrintGCDetails-XX:+PrintGCDateStamps-XX:+PrintGCTimeStamps# 输出到文件-Xloggc:gc.log# 完整配置示例-XX:+PrintGCDetails-XX:+PrintGCDateStamps-Xloggc:gc.log2.5 GC 线程数
# Parallel GC 线程数-XX:ParallelGCThreads=4# CMS 并发线程数-XX:ConcGCThreads=23. 调试与诊断参数 🔍
3.1 打印 JVM 信息
# 打印所有 JVM 参数-XX:+PrintFlagsFinal# 打印命令行参数-XX:+PrintCommandLineFlags3.2 OOM 时自动导出堆 dump
# OOM 时导出堆 dump-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/tmp/heap.hprof3.3 退出时打印 GC 信息
# 程序退出时打印 GC 摘要-XX:+PrintGCSummary3.4 远程调试
# 启用 JMX-Dcom.sun.management.jmxremote-Dcom.sun.management.jmxremote.port=9010-Dcom.sun.management.jmxremote.ssl=false-Dcom.sun.management.jmxremote.authenticate=false4. 典型配置模板 📋
4.1 微服务应用(通用)
java-server\-Xms512m-Xmx512m\# 堆大小-Xmn256m\# 新生代-XX:MetaspaceSize=128m\# 元空间-XX:MaxMetaspaceSize=128m\-XX:+UseG1GC\# 使用 G1-XX:MaxGCPauseMillis=200\# 停顿目标-XX:+PrintGCDetails\# 打印 GC 日志-XX:+PrintGCDateStamps\-Xloggc:gc.log\-jarapp.jar4.2 高并发 API 接口
java-server\-Xms1g-Xmx1g\# 堆大小 1GB-Xmn512m\# 新生代 512MB-XX:MetaspaceSize=256m\-XX:MaxMetaspaceSize=256m\-XX:+UseG1GC\-XX:MaxGCPauseMillis=100\# 更短的停顿目标-XX:InitiatingHeapOccupancyPercent=45\-XX:+HeapDumpOnOutOfMemoryError\-XX:HeapDumpPath=/tmp/oom.hprof\-XX:+PrintGCDetails\-Xloggc:gc.log\-jarapi.jar4.3 后台批处理任务
java-server\-Xms2g-Xmx2g\# 堆大小 2GB-Xmn1g\# 新生代 1GB-XX:MetaspaceSize=256m\-XX:MaxMetaspaceSize=256m\-XX:+UseParallelGC\# 吞吐量优先-XX:ParallelGCThreads=8\-XX:+UseParallelOldGC\-XX:+PrintGCDetails\-Xloggc:gc.log\-jarbatch.jar4.4 大内存应用(8GB+)
java-server\-Xms8g-Xmx8g\# 堆大小 8GB-Xmn4g\# 新生代 4GB-XX:MetaspaceSize=512m\-XX:MaxMetaspaceSize=512m\-XX:+UseG1GC\-XX:MaxGCPauseMillis=300\-XX:G1HeapRegionSize=16m\# 更大的 Region-XX:InitiatingHeapOccupancyPercent=40\-XX:+HeapDumpOnOutOfMemoryError\-XX:+PrintGCDetails\-Xloggc:gc.log\-jarlarge-app.jar4.5 开发测试环境
java-server\-Xms256m-Xmx256m\# 小堆内存-Xmn128m\-XX:+UseSerialGC\# Serial 收集器足够-XX:+PrintGCDetails\-Xloggc:gc.log\-jarapp.jar5. 参数优先级 📊
5.1 参数分类
| 优先级 | 参数类型 | 示例 |
|---|---|---|
| 高 | 内存大小 | -Xms,-Xmx,-Xmn |
| 高 | 收集器选择 | -XX:+UseG1GC |
| 中 | GC 阈值 | -XX:MaxGCPauseMillis |
| 中 | 日志配置 | -XX:+PrintGCDetails |
| 低 | 细节调优 | -XX:G1HeapRegionSize |
5.2 调优顺序
1. 先设堆大小(-Xms, -Xmx) 2. 选收集器(-XX:+UseG1GC) 3. 设停顿目标(-XX:MaxGCPauseMillis) 4. 开日志(-XX:+PrintGCDetails) 5. 观察后再微调6. 常见问题与解决 🔧
6.1 OOM:Java heap space
原因:堆内存不足
解决:
# 增大堆-Xms2g-Xmx2g6.2 OOM:Metaspace
原因:元空间不足(类太多)
解决:
# 增大元空间-XX:MetaspaceSize=512m-XX:MaxMetaspaceSize=512m6.3 GC 停顿过长
原因:堆太大、收集器不合适
解决:
# 1. 减小堆-Xms1g-Xmx1g# 2. 换 G1-XX:+UseG1GC-XX:MaxGCPauseMillis=200# 3. 减少对象晋升-XX:MaxTenuringThreshold=56.4 线程栈溢出
原因:递归调用太深
解决:
# 增大栈-Xss2m7. 快速参考表 📋
7.1 内存参数
| 参数 | 说明 | 示例 |
|---|---|---|
-Xms | 初始堆大小 | -Xms512m |
-Xmx | 最大堆大小 | -Xmx2g |
-Xmn | 新生代大小 | -Xmn256m |
-Xss | 线程栈大小 | -Xss1m |
-XX:MetaspaceSize | 元空间初始大小 | -XX:MetaspaceSize=256m |
-XX:MaxMetaspaceSize | 元空间最大大小 | -XX:MaxMetaspaceSize=512m |
7.2 GC 参数
| 参数 | 说明 | 示例 |
|---|---|---|
-XX:+UseSerialGC | Serial 收集器 | -XX:+UseSerialGC |
-XX:+UseParallelGC | Parallel 收集器 | -XX:+UseParallelGC |
-XX:+UseConcMarkSweepGC | CMS 收集器 | -XX:+UseConcMarkSweepGC |
-XX:+UseG1GC | G1 收集器 | -XX:+UseG1GC |
-XX:MaxGCPauseMillis | 停顿目标 | -XX:MaxGCPauseMillis=200 |
-XX:ParallelGCThreads | GC 线程数 | -XX:ParallelGCThreads=4 |
7.3 诊断参数
| 参数 | 说明 | 示例 |
|---|---|---|
-XX:+PrintGCDetails | 打印 GC 详情 | -XX:+PrintGCDetails |
-XX:+HeapDumpOnOutOfMemoryError | OOM 时 dump | -XX:+HeapDumpOnOutOfMemoryError |
-XX:HeapDumpPath | dump 路径 | -XX:HeapDumpPath=/tmp/heap.hprof |
-Xloggc | GC 日志文件 | -Xloggc:gc.log |
小结
- 内存参数:
-Xms/-Xmx(堆)、-Xss(栈)、-XX:MetaspaceSize(元空间) - GC 参数:收集器选择(
-XX:+UseG1GC)、停顿目标(-XX:MaxGCPauseMillis) - 诊断参数:GC 日志(
-XX:+PrintGCDetails)、OOM dump(-XX:+HeapDumpOnOutOfMemoryError) - 典型模板:微服务用 G1、高并发设停顿目标、批处理用 Parallel
- 调优顺序:先设堆大小 → 选收集器 → 设目标 → 开日志 → 观察微调
下一篇(025)预告:类加载:双亲委派与应用隔离——类加载器原理、打破双亲委派、Tomcat/Spring 类加载器隔离。