06.0 - JVM调优与排查索引
定位: JVM调优与生产问题排查的系统性方法论导航 面试高频度: ⭐⭐⭐⭐⭐ (调优是高级工程师的必备技能)
一、什么是JVM调优?为什么需要方法论?
JVM调优不是"抄几个参数"就能解决的事情。生产环境下的JVM问题千变万化,没有方法论支撑,只能靠猜。
两个核心认知:
- 调优是权衡的艺术 — 降低延迟往往增加吞吐量,减少Full GC次数可能增加Young GC暂停。不存在"最优参数",只有"最适合业务的参数"。
- 先诊断,后调优 — 调优最大的误区是"先加参数再观察"。正确的顺序永远是:现象 → 定位 → 分析 → 修复 → 验证。
二、调优方法论全景
┌─────────────────────────────────────────────────────────────────────────┐
│ JVM调优宏观流程 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 现象发现 │
│ ├── 用户反馈"系统变慢了" │
│ ├── 监控告警: CPU > 90%, 接口延迟 > 5s │
│ └── 系统日志: OutOfMemoryError, Full GC │
│ │ │
│ ▼ │
│ 初步定位 (工具三板斧) │
│ ├── jps -lv → 找到PID │
│ ├── jstat -gcutil → 看GC是否异常 │
│ └── top -H -p → 看线程CPU │
│ │ │
│ ▼ │
│ 深入分析 │
│ ├── 内存问题 → jmap / heap dump / MAT │
│ ├── 线程问题 → jstack / Arthas thread │
│ ├── CPU问题 → Arthas thread -n / profiler │
│ └── GC问题 → GC日志分析 / jstat持续监控 │
│ │ │
│ ▼ │
│ 确定根因 │
│ ├── 代码层面: 无限循环、大对象、连接未关闭 │
│ ├── 配置层面: -Xmx太小、GC选型不当 │
│ ├── 框架层面: 类加载泄漏、线程池配置错误 │
│ └── OS层面: 句柄/线程限制、Swap频繁 │
│ │ │
│ ▼ │
│ 实施修复 │
│ ├── 代码修复 → 发布 │
│ ├── JVM参数调整 → 重启 │
│ └── 架构优化 → 长期改进 │
│ │ │
│ ▼ │
│ 验证效果 │
│ ├── 指标对比: 调优前 vs 调优后 │
│ ├── 压测验证: 稳定性/延迟/吞吐量 │
│ └── 监控持续: 确认不再反弹 │
│ │
└─────────────────────────────────────────────────────────────────────────┘三、章节导航
| 章节 | 标题 | 核心内容 | 类型 |
|---|---|---|---|
| **JVM参数分类速查** | JVM参数分类速查 | 内存/GC/诊断/编译参数速查表 | 参考 |
| **常用工具(jps与jstat与jmap与jstack与jinfo)** | 常用工具 | jps/jstat/jmap/jstack/jinfo命令详解与实战 | 工具 |
| **图形化工具(JVisualVM与Arthas)** | 图形化工具 | JVisualVM可视化 + Arthas深度诊断 | 工具 |
| **OOM排查方法论** | OOM排查 | 5种OOM类型 + heap dump分析 + MAT | 方法论 |
| **CPU飙升排查方法论** | CPU飙升排查 | top→tid→jstack→分析 全流程 | 方法论 |
| **FullGC频繁排查方法论** | FullGC频繁排查 | GC日志分析 + 触发原因 + 调优方案 | 方法论 |
| **大厂实战案例库** | 大厂实战案例 | 5个真实生产事故复盘 | 案例 |
四、四件套速查
jps - JVM进程状态
| 命令 | 说明 | 使用频率 |
|---|---|---|
jps -l | 显示完整主类名(最常用) | ⭐⭐⭐⭐⭐ |
jps -v | 显示JVM参数 | ⭐⭐⭐⭐ |
jps -m | 显示main方法参数 | ⭐⭐⭐ |
jps -lvm | 完整信息(组合使用) | ⭐⭐⭐⭐⭐ |
jstat - GC统计
| 命令 | 说明 | 使用频率 |
|---|---|---|
jstat -gc <pid> 1000 | GC各区域容量和使用量 | ⭐⭐⭐⭐⭐ |
jstat -gcutil <pid> 1000 | GC使用率百分比(最直观) | ⭐⭐⭐⭐⭐ |
jstat -gccause <pid> 1000 | 最近GC的原因 | ⭐⭐⭐⭐ |
jmap - 内存映射
| 命令 | 说明 | 风险 |
|---|---|---|
jmap -heap <pid> | 查看堆概要 | 低 |
jmap -histo <pid> | 查看类实例统计 | 低 |
jmap -histo:live <pid> | 先Full GC再统计 | ⚠️ 触发Full GC |
jmap -dump:format=b,file=h.hprof <pid> | 堆dump | ⚠️ 触发Full GC,生产慎用 |
jstack - 线程栈
| 命令 | 说明 | 使用频率 |
|---|---|---|
jstack <pid> | 线程dump | ⭐⭐⭐⭐⭐ |
jstack -l <pid> | 包含锁信息 | ⭐⭐⭐⭐ |
jstack -m <pid> | 包含native栈 | ⭐⭐ |
五、三板斧快速诊断
生产系统出现性能问题时,按以下优先级排查:
板斧一:CPU问题
症状: 接口响应慢,CPU 100%
流程: top → top -H -p → jstack → 定位代码
工具: top + jstack / Arthas thread -n 3
详见: [[06.5-CPU飙升排查方法论]]板斧二:内存问题
症状: OOM / 频繁GC / 内存持续上涨
流程: jstat -gc → jmap -histo → heap dump → MAT分析
工具: jstat + jmap + MAT / Eclipse Memory Analyzer
详见: [[06.4-OOM排查方法论]]板斧三:GC问题
症状: 频繁Full GC / GC暂停过长
流程: -XX:+PrintGCDetails → GC日志分析 → 参数调整
工具: jstat + GC日志 + GCeasy(在线分析)
详见: [[06.6-FullGC频繁排查方法论]]六、常见问题速查索引
| 问题现象 | 最可能原因 | 排查工具 | 相关章节 |
|---|---|---|---|
| 系统启动后逐渐变慢 | 内存泄漏 | jstat + heap dump | **OOM排查方法论** |
| CPU突然飙到100% | 死循环/Full GC | top + jstack | **CPU飙升排查方法论** |
| 接口偶尔超时 | Full GC暂停 | GC日志 | **FullGC频繁排查方法论** |
| 线程池任务不执行 | 死锁/线程阻塞 | jstack -l | **常用工具(jps与jstat与jmap与jstack与jinfo)** |
| Metaspace OOM | 类加载泄漏 | jstat -gc MC/MU | **OOM排查方法论** |
| 不出OOM但内存很高 | Direct Buffer泄漏 | jcmd VM.native_memory | **OOM排查方法论** |
七、面试视角
高频面试题
| 面试题 | 考察点 | 回答要点 |
|---|---|---|
| "线上CPU100%怎么排查?" | 排查方法论 | top → tid → jstack 四步法 |
| "OOM了怎么定位?" | 内存分析能力 | -XX:+HeapDumpOnOOM → MAT分析 |
| "JVM调优一般调什么?" | 调优全景认知 | 先诊断后调优,延迟/吞吐量权衡 |
| "遇到过什么JVM问题?" | 实战经验 | STAR法则描述现象-排查-根因-解决 |
| "Full GC频繁怎么办?" | GC原理理解 | 先确定触发原因,再针对处理 |
面试回答模板
Q: 线上CPU100%怎么排查? A: 分四步:1)
top找到Java进程PID 2)top -H -p <pid>找到CPU最高的线程TID 3)printf '%x\n' <tid>转十六进制 4)jstack <pid> | grep -A 30 <hex>定位代码行。更快的方案是用Arthas的thread -n 3直接看。
📚 相关链接
- **JVM文库设计文档** - 全库设计原则
- **批次1实施计划** - 内容建设计划
- **垃圾收集器详解(Serial到ZGC)** - GC收集器基础
- **GC日志分析** - GC日志解读
- **GC调优参数速查** - GC参数参考
- **Java堆** - 堆内存结构
- **方法区与元空间** - 方法区与元空间
- **直接内存** - 直接内存