一、先给这本书定位
它是什么
国内 JVM 领域的事实标杆书,中文世界里体系最完整的一本
★★★★ 独特价值:不只讲「怎么用」,更讲「为什么这样设计」——大量篇幅在讲权衡取舍
作者本人是 OpenJDK 贡献者,内容经得起推敲,勘误维护在 GitHub(fenixsoft/jvm_book)
它的骨架:五大部分 13 章
第一部分 走近 Java(第 1 章)—— 全景与历史
第二部分 自动内存管理(第 2-5 章)★★★ —— 调优的主战场,占全书分量最重
第三部分 虚拟机执行子系统(第 6-9 章)—— 类文件、类加载、字节码执行
第四部分 程序编译与代码优化(第 10-11 章)—— javac 前端 + JIT 后端
第五部分 高效并发(第 12-13 章)—— JMM 与锁优化
读完能到什么水平
★★★ 能看懂 GC 日志并定位内存问题,能独立完成堆大小与收集器选型
★★★ 能用 jcmd/jstat/jmap/JFR + MAT 走完一次完整的线上故障排查
★★ 能理解类加载机制、双亲委派及其被破坏的场景,能排查 NoClassDefFoundError 类问题
★★ 能从字节码层面解释 Java 语法糖、理解 JIT 优化为什么会/不会生效
★★ 能理解 JMM 的 happens-before 规则,写出不依赖运气的并发代码
⚠️ 它的时效性缺口(最重要的提醒)
本书基线 JDK 8-13,出版于 2019 年底,如今最新 LTS 已是 JDK 25(最新 GA 为 JDK 27)
★★★ CMS 收集器已在 JDK 14 被彻底移除(JEP 363)—— 书中 3.5.6 整整一节讲的东西已不能用于新项目
⚠️ 偏向锁(书中 13.3.5)已废弃并移除,JDK 15 起废弃(JEP 374)—— 请以官方文档核实当前状态
⚠️ jhat(书中 4.2.5)已从 JDK 移除,堆分析改用 MAT / JFR / jcmd
虚拟线程(书中 12.5「Java 与协程」当时还是展望)已于 JDK 21 正式发布(JEP 444)
JNI(书中第 13 章本地方法)正被 FFM API 取代(JDK 22 正式,JEP 454)
→ 解法见「7 版本演进对照」画布,务必与本书对照着读
它不覆盖什么(需另补)
JDK 21+ 的新特性:虚拟线程实战、分代 ZGC、FFM API、紧凑对象头
云原生场景:容器内存/CPU 感知、CRaC 快速启动、AppCDS 冷启动优化
系统化的性能工程方法论(本书第 5 章是案例式,不是方法论式)
GC 算法的理论深度(要读《The Garbage Collection Handbook》)
GraalVM / Native Image 的完整体系(书中 11.5 只讲了 Graal 编译器本身)
二、学习主线:四阶段(按「先能救火,再懂原理」排序)
阶段一 · 内存与调优主线(第 2-5 章)★★★
为什么先学:这是你「完成调优工作」目标的直接支撑,也是最容易出成果的部分
目标口号:看得懂 GC 日志、找得到内存泄漏、选得对收集器
关键章节:第 2 章内存区域、第 3 章垃圾收集器、第 4 章工具、第 5 章案例
阶段产出:一次完整的 OOM 排查记录 + 一份你自己项目的 GC 调优前后对比
★ 建议顺序:先读第 2 章 → 跳到第 4 章工具 → 回读第 3 章 → 最后第 5 章
(先有工具手感再啃收集器原理,比从头顺读更容易坚持)
阶段二 · 执行子系统(第 6-9 章)
目标口号:知道一个 class 文件是怎么跑起来的
关键章节:第 7 章类加载机制(★ 最实用)、第 8 章字节码执行引擎
阶段产出:手写一个类加载器实现热部署或隔离;用 ASM 或 javap 读懂一段字节码
★ 优先级:第 7 章 、第 9 章 、第 8 章 、 第 6 章(第 6 章可当参考书查)
阶段三 · 编译与优化(第 10-11 章)
目标口号:解释清楚「为什么我这段代码没被优化」
关键章节:11.2 即时编译器、11.4 编译器优化技术(逃逸分析、方法内联)
阶段产出:用 -XX:+PrintCompilation 观察一次分层编译;验证一次逃逸分析导致的栈上分配
★ 第 10 章前端编译偏语言实现,可按兴趣取舍;第 11 章后端与调优关系更直接
阶段四 · 并发与内存模型(第 12-13 章)
目标口号:不再靠运气写并发代码
关键章节:12.3 JMM 与 happens-before、13.2 线程安全、13.3 锁优化
阶段产出:能用 JMM 规则解释一个真实的可见性 bug;用 async-profiler 抓一次锁竞争火焰图
★★ 提醒:这部分必须配《Java 并发编程实战》与 Aleksey Shipilëv 的 JMM Pragmatics,本书讲得清楚但深度有限
三、时间节奏建议
强度:每天 1.5-2 小时,每周 5-6 天,全书约 12-16 周
阶段一(第 2-5 章)5-6 周 —— 分量最重,也是回报最高
阶段二(第 6-9 章)3 周
阶段三(第 10-11 章)2 周
阶段四(第 12-13 章)2-3 周
第 1 章 1 周(含自己动手编译一次 JDK)
★★★ 铁律:这本书不动手等于没读
书里每一个「实战」小节都要跑一遍,每一个参数都要改一次看效果
作者配套代码在 GitHub fenixsoft/jvm_book,直接 clone 下来跑
前置要求(不满足会很痛苦)
Java 基础扎实:《Java 核心技术》卷 I 水平(你已在学,衔接正好)
会用命令行、能看懂基本的 C/C++ 概念(第 1 章编译 JDK、第 13 章 JNI 需要)
有一台能装 Linux 或 WSL2 的机器(很多工具在 Windows 上体验差)
卡壳上限 40 分钟
JVM 问题往往需要查官方文档或 HotSpot 源码,超时就去搜而不是硬磕
把查不清的问题记进问题本,积累到一定量再集中攻克
四、每章四步法(核心方法论)
读:先通读,标记不懂的术语,不追根究底
本书术语密度高,第一遍允许 60% 理解度
★★★ 跑:书里所有实战代码必须亲手跑通
clone fenixsoft/jvm_book,逐个模块运行
跑完改:改参数、改数据规模、改 JDK 版本,观察差异
★ 关键动作:把书中结论在新版 JDK 上重跑一遍,验证是否仍成立
(很多结论在 JDK 17/21 上已经变了,这正是你的收获点)
画图:把机制画成自己的图
内存区域布局图、GC 分代流程图、类加载时序图、对象头结构图
★ 画不出来说明没懂,回去重读
讲:合上书复述「这章解决了什么问题、代价是什么」
本书精华在于权衡,讲不出代价就是没读懂
进阶:写成技术博客或提交到 Git,形成自己的 JVM 知识库
七、验收闭环
每阶段结束做一次「不看书写一遍」
阶段一:给你一份 GC 日志,盲分析出收集器类型、停顿分布、是否存在问题
阶段二:盲画出类加载全过程与双亲委派流程
阶段三:盲写一段代码验证逃逸分析是否生效,并解释观察结果
阶段四:盲写 happens-before 规则清单,并解释一个可见性 bug
最终验收:「10 避坑与验收」画布里的清单能打钩 80% 以上
打钩标准必须是真机操作成功并留下数据,不接受「我觉得懂了」
★★★ 一个高价值的自我检验
拿一个你熟悉的项目(或开源项目),完整做一次调优:
采集基线 → 定位瓶颈 → 提出假设 → 改参数/改代码 → 验证 → 写报告
能独立走完这个闭环,你就真的具备调优能力了
六、三个随身资产(长期复利)
参数手册:按场景归档 JVM 参数,自己整理一份
内存类:-Xms/-Xmx/-Xss/-XX:MetaspaceSize/-XX:MaxDirectMemorySize
GC 类:-XX:+UseG1GC/-XX:+UseZGC/-XX:MaxGCPauseMillis/-XX:G1HeapRegionSize
诊断类:-XX:+HeapDumpOnOutOfMemoryError/-Xlog:gc*/-XX:+PrintCompilation
★ 每个参数记下:作用、默认值、你实测的效果、副作用
故障案例库:现象 → 排查路径 → 根因 → 解法 → 预防
起步先记书中第 5 章的 8 个案例,改写成你自己的复现步骤
每次线上/练习中遇到的问题都追加进去,这是你最值钱的资产
实验记录:每次调参都留下 before/after 数据
格式:JDK 版本 + 参数组合 + 负载描述 + GC 次数/停顿时间/吞吐量
★ 没有对照数据的调优都是玄学,养成留证据的习惯
五、环境搭建(第 1 周必须搞定)★★★
多版本 JDK 并存(最关键的一步)
至少装三个:JDK 8(验证书中原始结论)、JDK 17 或 21(主流 LTS)、JDK 25(最新 LTS)
★ 为什么必须多版本:本书基于 JDK 8-13,你要亲眼看到差异才算真学会
推荐发行版:Eclipse Temurin(Adoptium,免费、纯净)或 Oracle JDK
Windows 建议用 WSL2 + Ubuntu,Linux 环境下的工具链体验完整得多
必装工具清单
JDK 自带:jcmd ★★★、jstat、jps、jhsdb、jfr、jshell、jconsole
独立下载:JDK Mission Control(JMC,开源但不随 JDK 分发)
Eclipse MAT ★★★(堆转储分析,替代已移除的 jhat)
async-profiler ★★★(低开销采样,出火焰图,无 safepoint 偏差)
Arthas(阿里开源,线上诊断神器,无需重启)
IDE:IntelliJ IDEA(内置 profiler 与 JFR 支持,社区版够用)
实验素材
GitHub fenixsoft/jvm_book —— 本书官方配套代码,含各类 OOM 复现样例
自己写压力测试:用 JMH 做基准测试,别用 System.currentTimeMillis 土法计时
★ 造故障的常用手法:-Xmx 限小 + 无限往集合里塞对象 = 堆 OOM;递归不返回 = 栈溢出;死循环 + sleep = CPU 飙高;Thread.sleep(MAX_VALUE) 大量起线程 = 线程堆积
★★★ GC 日志必须从第一天就开着
JDK 9+ 统一日志格式:-Xlog:gc*:file=gc.log:time,uptime,level,tags
JDK 8 老格式:-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log
★ 注意:书中用的是 JDK 8 老格式参数,新版必须换成 -Xlog(这是最常见的踩坑点)