JVM 速查表
快速查阅JVM常用命令、参数和概念。本速查表涵盖了日常开发和运维中最常用的JVM诊断和调优工具。
常用命令速查
进程管理命令
| 命令 | 用途 | 示例 |
|---|---|---|
jps | 列出Java进程 | jps -lmv |
jstat | JVM统计信息 | jstat -gc <pid> 1000 |
jmap | 内存映射 | jmap -dump:format=b,file=heap.hprof <pid> |
jstack | 线程堆栈 | jstack -l <pid> |
jinfo | 配置信息 | jinfo -flags <pid> |
jcmd | 多功能诊断 | jcmd <pid> help |
jstat 常用选项详解
jstat 是监控 JVM 运行状态最常用的命令,可以实时查看 GC、类加载、编译等信息。
# 类加载统计
jstat -class <pid> 1000 5
# 编译统计
jstat -compiler <pid>
# GC统计(每秒刷新,共5次)
jstat -gc <pid> 1000 5
# GC容量信息
jstat -gccapacity <pid>
# GC利用率(百分比形式,更易读)
jstat -gcutil <pid> 1000
# GC原因和统计
jstat -gccause <pid> 1000
# 新生代详细统计
jstat -gcnew <pid>
# 老年代详细统计
jstat -gcold <pid>
jstat -gc 输出列含义:
| 列名 | 含义 |
|---|---|
| S0C/S1C | Survivor 0/1 区容量(KB) |
| S0U/S1U | Survivor 0/1 区已使用(KB) |
| EC/EU | Eden 区容量/已使用(KB) |
| OC/OU | 老年代容量/已使用(KB) |
| MC/MU | 元空间容量/已使用(KB) |
| YGC/YGCT | Young GC 次数/总时间 |
| FGC/FGCT | Full GC 次数/总时间 |
| GCT | GC 总时间 |
jmap 常用选项详解
jmap 用于生成堆转储和分析内存分布,是诊断内存问题的重要工具。
# 查看堆配置信息
jmap -heap <pid>
# 查看对象统计(按大小排序)
jmap -histo <pid> | head -30
# 查看存活对象统计(会触发Full GC)
jmap -histo:live <pid> | head -30
# 生成完整堆转储
jmap -dump:format=b,file=heap.hprof <pid>
# 只转储存活对象(会触发Full GC)
jmap -dump:live,format=b,file=heap_live.hprof <pid>
# 查看类加载器统计
jmap -clstats <pid>
# 查看最终化队列
jmap -finalizerinfo <pid>
jstack 常用选项详解
jstack 用于获取线程堆栈信息,诊断线程死锁、CPU 飙高等问题。
# 打印线程堆栈
jstack <pid>
# 打印额外锁信息
jstack -l <pid>
# 输出到文件
jstack <pid> > thread_dump.txt
# 强制打印(无响应时使用)
jstack -F <pid>
jcmd 完整命令列表
jcmd 是 JDK 7+ 推荐的多功能诊断工具,可以替代多个传统命令。
# 查看所有可用命令
jcmd <pid> help
# JVM版本信息
jcmd <pid> VM.version
# JVM启动参数
jcmd <pid> VM.flags
jcmd <pid> VM.command_line
jcmd <pid> VM.system_properties
# 运行时信息
jcmd <pid> VM.info
# 线程信息
jcmd <pid> Thread.print
jcmd <pid> Thread.print -l # 包含锁信息
# 堆信息
jcmd <pid> GC.heap_info
jcmd <pid> GC.class_histogram
jcmd <pid> GC.heap_dump filename=heap.hprof
# 触发GC
jcmd <pid> GC.run
# 本地内存跟踪
jcmd <pid> VM.native_memory summary
jcmd <pid> VM.native_memory detail
# JIT编译器信息
jcmd <pid> Compiler.CodeHeap_Analytics
# JFR录制
jcmd <pid> JFR.start name=test duration=60s filename=recording.jfr
jcmd <pid> JFR.dump name=test filename=dump.jfr
jcmd <pid> JFR.stop name=test
内存参数
堆内存参数
| 参数 | 说明 | 示例 |
|---|---|---|
-Xms | 初始堆大小 | -Xms2g |
-Xmx | 最大堆大小 | -Xmx2g |
-Xmn | 新生代大小 | -Xmn512m |
-XX:NewRatio | 新老年代比例 | -XX:NewRatio=2 |
-XX:SurvivorRatio | Eden/Survivor比例 | -XX:SurvivorRatio=8 |
-XX:MaxTenuringThreshold | 对象晋升年龄阈值 | -XX:MaxTenuringThreshold=15 |
-XX:PretenureSizeThreshold | 大对象阈值 | -XX:PretenureSizeThreshold=3m |
堆内存设置原则:
-Xms和-Xmx设为相同值,避免动态扩容- 堆大小通常为物理内存的 50%-80%
- 新生代一般为堆的 1/3 到 1/4
元空间参数
| 参数 | 说明 | 示例 |
|---|---|---|
-XX:MetaspaceSize | 初始元空间大小 | -XX:MetaspaceSize=128m |
-XX:MaxMetaspaceSize | 最大元空间大小 | -XX:MaxMetaspaceSize=512m |
-XX:MinMetaspaceFreeRatio | GC后最小空闲比例 | -XX:MinMetaspaceFreeRatio=40 |
-XX:MaxMetaspaceFreeRatio | GC后最大空闲比例 | -XX:MaxMetaspaceFreeRatio=70 |
栈内存参数
| 参数 | 说明 | 示例 |
|---|---|---|
-Xss | 每个线程的栈大小 | -Xss1m |
-XX:ThreadStackSize | 线程栈大小(等效-Xss) | -XX:ThreadStackSize=1024 |
栈大小计算:
- 每个线程独立栈空间
- 总栈内存 = 线程数 × 栈大小
- 深递归需要更大的栈
直接内存参数
| 参数 | 说明 | 示例 |
|---|---|---|
-XX:MaxDirectMemorySize | 最大直接内存 | -XX:MaxDirectMemorySize=256m |
-XX:+DisableExplicitGC | 禁用System.gc() | -XX:+DisableExplicitGC |
直接内存使用场景:
- NIO ByteBuffer.allocateDirect()
- Netty 等网络框架
- 注意:直接内存不足会触发 Full GC
JIT编译器参数
分层编译
| 参数 | 说明 | 示例 |
|---|---|---|
-XX:+TieredCompilation | 启用分层编译(默认开启) | -XX:+TieredCompilation |
-XX:TieredStopAtLevel | 最高编译级别 | -XX:TieredStopAtLevel=1 |
-XX:+EnableJVMCI | 启用JVMCI(Graal编译器) | -XX:+EnableJVMCI |
编译级别说明:
- Level 0:解释执行
- Level 1:简单C1编译(快速编译,基本优化)
- Level 2:受限C1编译
- Level 3:完整C1编译
- Level 4:C2编译(深度优化,编译时间长)
编译器优化
| 参数 | 说明 | 示例 |
|---|---|---|
-XX:+PrintCompilation | 打印编译信息 | -XX:+PrintCompilation |
-XX:+PrintInlining | 打印内联信息 | -XX:+PrintInlining |
-XX:CompileThreshold | 触发编译的方法调用次数 | -XX:CompileThreshold=10000 |
-XX:OnStackReplacePercentage | OSR触发比例 | -XX:OnStackReplacePercentage=140 |
代码缓存
| 参数 | 说明 | 示例 |
|---|---|---|
-XX:InitialCodeCacheSize | 初始代码缓存 | -XX:InitialCodeCacheSize=160k |
-XX:ReservedCodeCacheSize | 最大代码缓存 | -XX:ReservedCodeCacheSize=240m |
-XX:CodeCacheExpansionSize | 代码缓存扩展大小 | -XX:CodeCacheExpansionSize=64k |
-XX:+UseCodeCacheFlushing | 启用代码缓存刷新 | -XX:+UseCodeCacheFlushing |
代码缓存不足症状:
- JIT编译停止
- 性能下降
- 警告:
CodeCache is full. Compiler has been disabled
线程相关参数
| 参数 | 说明 | 示例 |
|---|---|---|
-Xss | 线程栈大小 | -Xss1m |
-XX:ParallelGCThreads | 并行GC线程数 | -XX:ParallelGCThreads=8 |
-XX:ConcGCThreads | 并发GC线程数 | -XX:ConcGCThreads=4 |
-XX:+UseThreadPriorities | 启用线程优先级 | -XX:+UseThreadPriorities |
-XX:ThreadPriorityPolicy | 线程优先级策略 | -XX:ThreadPriorityPolicy=1 |
日志参数
JDK 9+ 统一日志(推荐)
# 基本格式
-Xlog:<selector>[:<output>[:<decorators>][:<output-options>]]
# 常用配置示例
# 输出所有GC日志到文件
-Xlog:gc*:file=/var/log/gc.log:time,level,tags
# 输出GC详情和堆信息
-Xlog:gc*,gc+heap=debug:file=gc.log:time
# 输出类加载信息
-Xlog:class+load=info:file=classload.log
# 输出JIT编译信息
-Xlog:jit+compilation=info:file=jit.log
# 输出GC原因
-Xlog:gc+cause:file=gc.log
# 日志文件滚动(最多5个文件,每个100MB)
-Xlog:gc*:file=/var/log/gc.log:time,level,tags:filecount=5,filesize=100m
常用选择器:
| 选择器 | 说明 |
|---|---|
gc* | 所有GC相关日志 |
gc+heap | 堆相关信息 |
gc+cause | GC原因 |
gc+ergo* | GC自适应调节 |
gc+phases | GC各阶段耗时 |
class+load | 类加载 |
jit+compilation | JIT编译 |
os+thread | 线程相关 |
JDK 8 及之前(已弃用)
# GC日志
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCTimeStamps
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintHeapAtGC
-Xloggc:/path/to/gc.log
垃圾收集器参数
Serial 收集器
单线程收集器,适合小内存、单核环境。
-XX:+UseSerialGC # 启用Serial收集器
特点:
- 新生代使用复制算法
- 老年代使用标记-整理算法
- 单线程执行,会暂停所有应用线程
- 简单高效,没有线程交互开销
适用场景:
- 客户端应用
- 单核服务器
- 堆内存小于100MB
Parallel 收集器(吞吐量优先)
多线程收集器,关注吞吐量。
-XX:+UseParallelGC # 新生代使用Parallel
-XX:+UseParallelOldGC # 老年代使用Parallel(JDK8默认配对)
-XX:MaxGCPauseMillis=200 # 最大停顿时间目标
-XX:GCTimeRatio=99 # 吞吐量目标(99表示GC时间占1%)
-XX:+UseAdaptiveSizePolicy # 自适应调节策略
-XX:ParallelGCThreads=8 # GC线程数
吞吐量计算:
- GCTimeRatio=99 表示 GC时间:应用时间 = 1:99
- 即 GC时间占比 = 1/(1+99) = 1%
G1 收集器(推荐)
JDK 9+ 默认收集器,平衡吞吐量和延迟。
# 基本配置
-XX:+UseG1GC # 启用G1(JDK9+默认)
-XX:MaxGCPauseMillis=200 # 最大停顿时间目标
# Region配置
-XX:G1HeapRegionSize=4m # Region大小(1-32MB,2的幂)
# 年轻代配置
-XX:G1NewSizePercent=5 # 年轻代最小占比
-XX:G1MaxNewSizePercent=60 # 年轻代最大占比
# 并发标记配置
-XX:InitiatingHeapOccupancyPercent=45 # 触发并发标记的堆占用阈值
-XX:G1HeapReservePercent=10 # 保留空间百分比
# Mixed GC配置
-XX:G1MixedGCCountTarget=8 # Mixed GC次数目标
-XX:G1MixedGCLiveThresholdPercent=85 # Region存活对象阈值
-XX:G1HeapWastePercent=5 # 允许浪费空间百分比
# 大对象配置
# 大对象 = 超过Region一半的对象
-XX:G1HeapRegionSize # Region大小影响大对象阈值
# 高级配置
-XX:+UseStringDeduplication # 启用字符串去重
-XX:G1PeriodicGCInterval=0 # 周期性GC间隔(毫秒),0禁用
G1 调优建议:
- 不要设置年轻代大小(
-Xmn),让 G1 自动调整 - 首先调整停顿时间目标
- 如果停顿时间不达标,再调整其他参数
ZGC 收集器(超低延迟)
JDK 11+ 可用,JDK 21+ 推荐使用分代 ZGC。
# JDK 21+ 推荐:分代ZGC
-XX:+UseZGC -XX:+ZGenerational
# JDK 11-20:非分代ZGC
-XX:+UseZGC
# 内存配置
-XX:SoftMaxHeapSize=4g # 软最大堆大小
-XX:MaxHeapSize=8g # 硬最大堆大小
# 内存归还配置
-XX:-ZUncommit # 禁用内存归还(延迟敏感场景)
-XX:ZUncommitDelay=300 # 内存归还延迟(秒)
# 性能优化
-XX:+UseLargePages # 启用大页
-XX:+AlwaysPreTouch # 预分配内存
-XX:ConcGCThreads=4 # 并发GC线程数
# 其他参数
-XX:ZAllocationSpikeTolerance=2 # 分配峰值容忍度
-XX:ZFragmentationLimit=5 # 最大碎片率百分比
ZGC 选择建议:
- JDK 21+ 务必使用分代ZGC(
-XX:+ZGenerational) - 大内存场景(>32GB)首选
- 延迟敏感场景首选
Shenandoah 收集器
OpenJDK 的低延迟收集器。
-XX:+UseShenandoahGC # 启用Shenandoah
-XX:ShenandoahGCMode=normal # GC模式
-XX:ShenandoahGCHeuristics=adaptive # 启发式策略
-XX:ConcGCThreads=4 # 并发GC线程数
-XX:ShenandoahMinRegionSize=256k # 最小Region大小
-XX:ShenandoahMaxRegionSize=32m # 最大Region大小
启发式策略选项:
adaptive:自适应(默认)compact:更积极回收,适合内存受限环境static:固定阈值aggressive:激进模式,用于测试
GC日志参数
JDK 8及之前
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCCause
-XX:+PrintHeapAtGC
-Xloggc:/path/to/gc.log
JDK 9及之后
-Xlog:gc*:file=/path/to/gc.log:time,level,tags
-Xlog:gc+heap=debug
-Xlog:gc+ergo*=trace
内存区域
运行时数据区
堆内存结构
类加载器层次
垃圾收集器对比
| 收集器 | 算法 | 适用场景 | 停顿时间 | 特点 |
|---|---|---|---|---|
| Serial | 复制/标记-整理 | 客户端、小内存(小于100MB) | 较长 | 简单、单线程 |
| Parallel | 复制/标记-整理 | 吞吐量优先 | 长 | 多线程、高吞吐 |
| CMS | 标记-清除 | 低延迟(JDK 14已移除) | 较短 | 并发、有碎片 |
| G1 | 标记-整理+复制 | 服务端通用(默认) | 小于200ms | 可预测停顿 |
| ZGC | 染色指针 | 大内存、超低延迟 | 小于1ms | JDK 21分代ZGC推荐 |
| Shenandoah | Brooks指针 | 低延迟 | 小于10ms | 并发压缩 |
常用诊断场景
场景一:内存泄漏诊断
现象:内存持续增长,最终OOM
诊断步骤:
# 1. 确认问题:观察老年代使用趋势
jstat -gcutil <pid> 5000 10
# 2. 多次生成堆转储对比
jmap -dump:live,format=b,file=heap1.hprof <pid>
# 等待一段时间后
jmap -dump:live,format=b,file=heap2.hprof <pid>
# 3. 使用MAT分析
# - 打开两个堆转储
# - 对比对象数量变化
# - 查看Dominator Tree
# - 分析Leak Suspects报告
# - 找到GC Root引用链
# 4. 使用jcmd查看对象直方图
jcmd <pid> GC.class_histogram | head -30
MAT 分析要点:
- 关注
Shallow Heap和Retained Heap - 使用
Path to GC Roots查找引用链 - 检查
Thread Stack查看线程持有的对象
场景二:线程死锁诊断
现象:程序挂起,无响应
诊断步骤:
# 1. 使用jstack检测死锁
jstack -l <pid> | grep -A 30 "Found one Java-level deadlock"
# 2. 完整线程转储
jstack -l <pid> > thread_dump.txt
# 3. 使用jcmd获取线程信息
jcmd <pid> Thread.print -l
# 4. 使用VisualVM检测
# - 打开Threads标签页
# - 点击"Detect Deadlock"按钮
死锁输出示例:
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x00007f8b4c001000 (object 0x000000076b5c7d58)
which is held by "Thread-2"
"Thread-2":
waiting to lock monitor 0x00007f8b4c002000 (object 0x000000076b5c7d60)
which is held by "Thread-1"
场景三:CPU 飙高诊断
现象:CPU 使用率异常高
诊断步骤:
# 1. 找到高CPU的Java进程
top -H -p <pid>
# 或者使用ps
ps -eLo pid,tid,%cpu,cmd | grep java | sort -k3 -rn | head
# 2. 将线程ID转换为16进制
printf "%x\n" <thread_id>
# 3. 查看对应线程的堆栈
jstack <pid> | grep -A 30 <hex_thread_id>
# 4. 或使用jcmd
jcmd <pid> Thread.print | grep -A 30 <hex_thread_id>
# 5. 使用async-profiler分析CPU热点
./profiler.sh -d 30 -f cpu.html <pid>
Windows 系统诊断:
# 使用Process Explorer查看线程
# 或使用PowerShell
Get-Process -Id <pid> | Select-Object -ExpandProperty Threads
# 使用jstack获取线程信息
jstack <pid> > thread_dump.txt
场景四:频繁 Full GC 诊断
现象:频繁 Full GC,响应慢
诊断步骤:
# 1. 查看GC统计信息
jstat -gcutil <pid> 1000 20
# 2. 查看GC原因
jstat -gccause <pid> 1000
# 3. 分析GC日志
# 查找Full GC原因:System.gc()、元空间不足、晋升失败等
# 4. 检查是否有显式GC调用
jstack <pid> | grep -B 5 "System.gc"
# 5. 检查元空间使用
jcmd <pid> GC.heap_info | grep -i metaspace
常见 Full GC 原因:
- 老年代空间不足
- 元空间不足
- 显式调用
System.gc() - RMI 定期 GC
- 直接内存不足
- 堆转储时
场景五:OOM 快速诊断
现象:java.lang.OutOfMemoryError
诊断步骤:
# 1. 确定OOM类型
# Java heap space: 堆内存不足
# Metaspace: 元空间不足
# GC overhead limit exceeded: GC时间过长
# Direct buffer memory: 直接内存不足
# 2. 开启OOM时自动生成堆转储
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/path/to/dump
# 3. 查看内存使用情况
jmap -heap <pid>
# 4. 对象直方图分析
jmap -histo:live <pid> | head -50
# 5. 本地内存分析(JDK 8u191+)
jcmd <pid> VM.native_memory summary
场景六:应用启动慢诊断
现象:应用启动时间过长
诊断步骤:
# 1. 启用启动时间日志
-XX:+PrintFlagsFinal -Xlog:init+redefine=info
# 2. 使用JFR记录启动过程
-XX:StartFlightRecording=duration=60s,filename=startup.jfr
# 3. 分析类加载时间
-Xlog:class+load+time:file=classload.log
# 4. 检查并行加载
-XX:+UseParallelClassLoader
# 5. 使用CDS加速
# 生成共享归档
java -XX:ArchiveClassesAtExit=app.jsa -jar app.jar
# 使用共享归档
java -XX:SharedArchiveFile=app.jsa -jar app.jar
场景七:线程数过多诊断
现象:线程数量异常,内存压力大
诊断步骤:
# 1. 查看线程数
jstack <pid> | grep "^\"" | wc -l
# 2. 按线程状态分组统计
jstack <pid> | grep "java.lang.Thread.State" | sort | uniq -c
# 3. 查看线程栈内存占用
# 每个线程栈大小 × 线程数 = 总栈内存
# 4. 使用jcmd查看线程信息
jcmd <pid> Thread.print
# 5. 检查线程池配置
# 关注:核心线程数、最大线程数、队列大小
线程状态说明:
| 状态 | 说明 | 可能原因 |
|---|---|---|
| RUNNABLE | 运行中 | 正常 |
| BLOCKED | 阻塞等待锁 | 锁竞争 |
| WAITING | 无限等待 | Object.wait、LockSupport.park |
| TIMED_WAITING | 限时等待 | Thread.sleep、超时等待 |
| NEW | 新创建未启动 | 线程创建但未start |
| TERMINATED | 已终止 | 线程执行完成 |
性能调优模板
小型应用(< 1GB 堆内存)
适用于开发环境、测试环境、轻量级应用。
java -Xms512m -Xmx512m \
-XX:+UseSerialGC \
-Xlog:gc*:file=gc.log:time \
-jar app.jar
适用场景:
- 开发测试环境
- 客户端应用
- 容器资源受限(< 1GB 内存)
吞吐量优先(批处理任务)
适用于批处理、数据分析、后台计算任务。
java -Xmx8g -Xms8g \
-XX:+UseParallelGC \
-XX:NewRatio=1 \
-XX:SurvivorRatio=8 \
-XX:GCTimeRatio=99 \
-XX:+UseAdaptiveSizePolicy \
-XX:ParallelGCThreads=8 \
-Xlog:gc*:file=gc.log:time,level,tags \
-jar app.jar
适用场景:
- 大数据批处理
- 离线数据分析
- 报表生成
- 后台计算任务
关键参数说明:
NewRatio=1:年轻代和老年代各占一半GCTimeRatio=99:GC时间目标为1%
延迟优先(Web 服务)
适用于 Web 服务、API 网关、微服务。
java -Xmx4g -Xms4g \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=100 \
-XX:InitiatingHeapOccupancyPercent=35 \
-XX:G1HeapRegionSize=8m \
-XX:+UseStringDeduplication \
-Xlog:gc*:file=/var/log/gc.log:time,level,tags:filecount=5,filesize=50m \
-jar app.jar
适用场景:
- Web 服务
- REST API
- 微服务
- 对延迟敏感的应用
关键参数说明:
MaxGCPauseMillis=100:目标停顿时间100msInitiatingHeapOccupancyPercent=35:提前触发并发标记
超低延迟(JDK 21+ 推荐)
适用于金融交易、实时游戏、广告竞价等延迟敏感场景。
java -Xmx16g -Xms16g \
-XX:+UseZGC \
-XX:+ZGenerational \
-XX:+UseLargePages \
-XX:+AlwaysPreTouch \
-XX:-ZUncommit \
-XX:ConcGCThreads=8 \
-Xlog:gc*:file=/var/log/gc.log:time,level,tags \
-jar app.jar
适用场景:
- 高频交易系统
- 实时游戏服务器
- 广告竞价系统
- 金融风控系统
关键参数说明:
ZGenerational:启用分代ZGC(JDK 21+必须)AlwaysPreTouch:启动时预分配内存ZUncommit=false:禁用内存归还
大内存缓存服务
适用于缓存服务、数据索引、内存数据库。
# JDK 21+ 分代ZGC
java -Xmx64g -Xms64g \
-XX:+UseZGC \
-XX:+ZGenerational \
-XX:SoftMaxHeapSize=48g \
-XX:+UseLargePages \
-XX:+AlwaysPreTouch \
-Xlog:gc*:file=/var/log/gc.log:time,level,tags \
-jar cache-service.jar
# 或使用G1(如果延迟要求不那么严格)
java -Xmx64g -Xms64g \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-XX:G1HeapRegionSize=32m \
-XX:InitiatingHeapOccupancyPercent=40 \
-jar cache-service.jar
容器环境(Kubernetes)
适用于云原生、容器化部署。
# JDK 8u191+ / JDK 11+ 容器感知配置
java -XX:+UseContainerSupport \
-XX:MaxRAMPercentage=75.0 \
-XX:InitialRAMPercentage=75.0 \
-XX:MaxMetaspaceSize=256m \
-XX:MaxDirectMemorySize=512m \
-Xss512k \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=100 \
-Xlog:gc*:file=/logs/gc.log:time,level,tags:filecount=5,filesize=50m \
-jar app.jar
Kubernetes 资源配置建议:
resources:
limits:
memory: "4Gi"
cpu: "2"
requests:
memory: "3Gi"
cpu: "1"
# JVM 配置说明:
# - 容器限制4GB,JVM堆约75%=3GB
# - 预留1GB给操作系统、元空间、线程栈等
# - 注意:limits和requests不要设置差距过大
容器环境注意事项:
- 使用
UseContainerSupport自动识别容器资源 - 使用百分比配置比固定值更灵活
- 预留至少 25% 内存给非堆开销
- 注意 CPU 限制影响 GC 线程数
Spring Boot 应用
Spring Boot 应用的推荐配置。
java -Xmx2g -Xms2g \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=100 \
-XX:+AlwaysPreTouch \
-XX:+DisableExplicitGC \
-XX:+UseStringDeduplication \
-Xlog:gc*:file=/var/log/gc.log:time,level,tags:filecount=5,filesize=50m \
-Djava.security.egd=file:/dev/./urandom \
-Dspring.profiles.active=prod \
-jar app.jar
关键参数说明:
DisableExplicitGC:禁用 System.gc()(Spring 有时会调用)UseStringDeduplication:字符串去重,减少内存占用java.security.egd:解决启动时随机数生成慢的问题
微服务网关
高并发 API 网关配置。
java -Xmx4g -Xms4g \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=50 \
-XX:InitiatingHeapOccupancyPercent=30 \
-XX:G1HeapRegionSize=16m \
-XX:MaxDirectMemorySize=1g \
-XX:+UseStringDeduplication \
-XX:+DisableExplicitGC \
-Xlog:gc*:file=/var/log/gc.log:time,level,tags \
-jar gateway.jar
关键参数说明:
MaxGCPauseMillis=50:更严格的停顿时间目标MaxDirectMemorySize=1g:网关通常有大量直接内存使用
常用JVM版本
JDK 版本特性对照表
| JDK版本 | 发布日期 | 主要特性 | LTS | GC默认 |
|---|---|---|---|---|
| JDK 8 | 2014-03 | Lambda、Stream API、方法引用 | ✓ | Parallel |
| JDK 11 | 2018-09 | HTTP Client、var关键字、ZGC(实验性) | ✓ | G1 |
| JDK 17 | 2021-09 | Sealed Classes、Pattern Matching、Record | ✓ | G1 |
| JDK 21 | 2023-09 | Virtual Threads、Generational ZGC、Pattern Matching for Switch | ✓ | G1 |
| JDK 25 | 2025-09 | 预计下一个LTS版本 | ✓(预计) | G1 |
LTS 版本选择建议
JDK 8:
- 企业遗留系统、最大兼容性
- 仍有大量生产环境使用
- 注意:CMS收集器已移除
JDK 11:
- 过渡选择,稳定且支持新特性
- HTTP Client API 完善
- ZGC 开始可用(实验性)
JDK 17:
- 当前主流选择,性能和特性平衡
- Record 和 Sealed Classes 成熟
- 建议新项目使用
JDK 21:
- 最新LTS,推荐升级目标
- Virtual Threads 是重大改进(虚拟线程)
- 分代 ZGC 是重大改进
- Spring Boot 3.2+ 完美支持
GC 收集器演进
| JDK版本 | GC 支持情况 |
|---|---|
| JDK 8 | Serial、Parallel、CMS、G1 |
| JDK 9+ | 移除 CMS(可用但弃用) |
| JDK 11 | 新增 ZGC(实验性) |
| JDK 12 | 新增 Shenandoah |
| JDK 14 | 移除 CMS |
| JDK 15 | ZGC 正式可用 |
| JDK 21 | 分代 ZGC 正式可用 |
迁移注意事项
JDK 8 → JDK 11:
- CMS 收集器不再推荐
- JavaFX 从 JDK 中移除
- 需要添加模块依赖(
--add-modules)
JDK 11 → JDK 17:
- Security Manager 弃用
- RMI Activation 移除
- Nashorn JavaScript 引擎移除
JDK 17 → JDK 21:
- Security Manager 更严格的弃用
- 分代 ZGC 推荐
- Virtual Threads 需要注意线程池使用方式
诊断命令快速参考
问题诊断速查表
| 问题现象 | 首选命令 | 辅助命令 |
|---|---|---|
| 内存泄漏 | jmap -histo:live | jmap -dump, MAT |
| CPU 飙高 | top -H -p + jstack | async-profiler |
| 线程死锁 | jstack -l | VisualVM |
| 频繁 GC | jstat -gcutil | GC 日志分析 |
| OOM | jmap -heap | -XX:+HeapDumpOnOutOfMemoryError |
| 启动慢 | -Xlog:class+load+time | JFR |
| 类加载问题 | jstat -class | -verbose:class |
命令速查卡片
┌─────────────────────────────────────────────────────────────────┐
│ JVM 诊断命令速查 │
├─────────────────────────────────────────────────────────────────┤
│ 进程信息 │
│ jps -lmv 列出所有Java进程 │
│ jinfo -flags <pid> 查看JVM参数 │
│ jcmd <pid> VM.flags 查看所有JVM参数 │
├─────────────────────────────────────────────────────────────────┤
│ 内存诊断 │
│ jstat -gcutil <pid> 1000 实时GC统计 │
│ jmap -heap <pid> 堆配置信息 │
│ jmap -histo <pid> 对象统计 │
│ jmap -dump:file=heap.hprof 生成堆转储 │
│ jcmd <pid> GC.heap_info 堆信息 │
├─────────────────────────────────────────────────────────────────┤
│ 线程诊断 │
│ jstack -l <pid> 线程堆栈(含锁信息) │
│ jcmd <pid> Thread.print 线程信息 │
├─────────────────────────────────────────────────────────────────┤
│ 类加载 │
│ jstat -class <pid> 类加载统计 │
│ jcmd <pid> GC.class_histogram 类直方图 │
├─────────────────────────────────────────────────────────────────┤
│ GC 相关 │
│ jstat -gc <pid> 1000 详细GC统计 │
│ jstat -gccause <pid> GC原因 │
│ jcmd <pid> GC.run 触发GC │
├─────────────────────────────────────────────────────────────────┤
│ JFR 录制 │
│ jcmd <pid> JFR.start name=test duration=60s filename=out.jfr │
│ jcmd <pid> JFR.dump name=test filename=dump.jfr │
│ jcmd <pid> JFR.stop name=test │
└─────────────────────────────────────────────────────────────────┘
参考资源
官方文档
工具下载
- Eclipse MAT - 堆转储分析
- async-profiler - 低开销性能分析
- Arthas - 阿里开源诊断工具
- GCViewer - GC日志可视化
- GCEasy - 在线GC日志分析