JVM概述
JVM(Java Virtual Machine,Java 虚拟机)是 Java 技术体系的运行时核心。Java 代码经过编译后生成字节码,字节码由 JVM 加载、验证、执行,并在运行期间完成内存管理、垃圾回收、即时编译、线程调度协作、监控诊断等工作。
对业务开发者来说,JVM 不是只在面试里出现的知识点。线上服务的启动速度、吞吐量、延迟、内存占用、Full GC、CPU 飙高、线程死锁、内存泄漏、类加载冲突,背后往往都和 JVM 有关。
关于 JVM 知识点的相关博客文章:
# 1. JVM 学习路径
JVM 可以按三个阶段学习。
# 1.1 新手阶段
先理解 Java 程序如何运行:
.java文件如何变成.class文件。- JVM 如何加载类。
- 堆、栈、方法区分别存什么。
- 对象为什么不需要手动释放。
- 垃圾回收大致做什么。
这个阶段目标是建立全局地图,不必一开始陷进各种参数和 GC 日志。
# 1.2 进阶阶段
开始理解运行时细节:
- 类加载生命周期和双亲委派模型。
- 对象创建、内存布局、引用类型。
- 新生代、老年代、对象晋升。
- 可达性分析和常见垃圾回收算法。
- JIT、热点代码、逃逸分析、锁优化。
- 常见 JVM 参数和诊断工具。
这个阶段目标是能看懂 JVM 问题,而不是只会背概念。
# 1.3 高级阶段
重点转向生产排障和调优:
- 如何分析 OOM。
- 如何分析 CPU 飙高。
- 如何分析频繁 Full GC。
- 如何看 GC 日志。
- 如何生成和分析堆转储、线程转储。
- 如何在容器环境中配置 JVM。
- 如何在吞吐、延迟、内存占用之间做取舍。
这个阶段的核心不是“调参数”,而是用证据定位瓶颈,再用最小改动解决问题。
# 2. JVM 的核心组成
JVM 可以从五个模块理解:
| 模块 | 作用 |
|---|---|
| 类加载子系统 | 加载、验证、准备、解析、初始化类 |
| 运行时数据区 | 管理堆、栈、方法区、程序计数器等内存区域 |
| 执行引擎 | 解释执行、JIT 编译、执行本地机器码 |
| 垃圾回收系统 | 自动识别和回收不再使用的对象 |
| 监控诊断体系 | 提供日志、转储、命令行工具、JFR 等诊断能力 |
一段 Java 代码的运行过程可以简化为:
Java源码 -> javac编译 -> class字节码 -> 类加载 -> 运行时内存 -> 执行引擎 -> GC与诊断
更细一点看,JVM 不是单点组件,而是一条运行链路:
┌────────────┐
│ Java 源码 │
└─────┬──────┘
│ javac / 其他 JVM 语言编译器
▼
┌────────────┐
│ Class 字节码 │
└─────┬──────┘
│ ClassLoader 加载、验证、准备、解析、初始化
▼
┌────────────┐
│ 方法区/元空间 │ 保存类元数据、常量池、方法信息
└─────┬──────┘
│ new、方法调用、字段访问
▼
┌────────────┐ ┌────────────┐
│ Java 堆 │ <───> │ 虚拟机栈 │
│ 对象实例 │ │ 栈帧/局部变量 │
└─────┬──────┘ └────────────┘
│
│ 解释执行 / JIT 编译 / 本地方法调用
▼
┌────────────┐
│ 机器码执行 │
└─────┬──────┘
│
│ GC、JFR、jstack、jmap、jcmd 观察和治理
▼
┌────────────┐
│ 线上运行状态 │
└────────────┘
这张图有一个很重要的含义:JVM 问题通常不会孤立出现。比如一个接口变慢,可能是对象分配过快引发 GC,也可能是锁竞争,也可能是 JIT 还没充分预热,也可能是线程池阻塞。学习 JVM 时要习惯把“语言语法、字节码、内存、线程、GC、工具”串起来看。
# 3. JVM 问题的排查主链路
JVM 排障建议按下面的链路推进:
现象
│
├─ CPU 高
│ ├─ top -Hp 找线程
│ ├─ jstack 找 Java 栈
│ └─ JFR / profiler 找热点
│
├─ 内存高 / OOM
│ ├─ 先看 OOM 类型
│ ├─ heap dump / class histogram
│ └─ MAT 分析 GC Roots 引用链
│
├─ 延迟抖动
│ ├─ 对齐 GC 日志和请求 RT
│ ├─ 看锁竞争、线程阻塞、IO 等待
│ └─ JFR 关联时间线
│
└─ 频繁 Full GC
├─ 看 GC 日志触发原因
├─ 看老年代回收前后变化
└─ 分析大对象、晋升、泄漏、元空间
在生产环境中,JVM 调优最怕“看见一个参数就想改”。正确顺序永远是:先描述现象,再采集证据,然后建立假设,最后小步验证。
# 4. 本章节目录
# 4.1 JVM 基础
# 4.2 类加载机制
# 4.3 运行时内存
# 4.4 垃圾回收
# 4.5 执行引擎与优化
# 4.6 工具与问题排查
# 4.7 调优实践与面试
# 5. 学习建议
学习 JVM 不建议从参数开始。参数只是结果,底层模型才是原因。更合理的顺序是:
- 先理解类加载和运行时内存。
- 再理解对象分配和垃圾回收。
- 接着学习 JIT 和运行时优化。
- 最后学习工具、日志和生产排障。
不同阶段的关注点可以这样划分:
| 阶段 | 学习重点 | 能力目标 |
|---|---|---|
| 新手 | 堆、栈、类加载、GC 基本概念 | 能解释 Java 程序怎么跑起来 |
| 中级 | 分代、对象晋升、JIT、常见工具 | 能看懂 GC 日志和线程栈 |
| 高级 | 低延迟 GC、JFR、容器内存、线上故障 | 能独立定位 JVM 生产问题 |
| 资深 | 性能模型、容量规划、可观测性体系 | 能设计 JVM 治理方案 |
# 6. Tips 快问快答
Q:学习 JVM 是不是先背参数?
A:不是。先理解运行机制,再学参数。参数是对机制的调节,不理解机制时改参数很容易误伤系统。
Q:JVM 调优是不是主要调 GC?
A:GC 很重要,但不是全部。很多性能问题来自业务对象模型、线程池、锁竞争、IO 等待、缓存策略和数据库访问。
Q:现代 Java 服务默认用什么 GC?
A:现代服务端 JDK 中通常从 G1 开始评估。低延迟大堆场景可以评估 ZGC 或 Shenandoah,但要用压测和监控验证。
Q:线上 JVM 问题第一步做什么?
A:先保留证据。线程 dump、GC 日志、堆 dump、JFR、业务日志和系统指标,往往比立即改参数更重要。
# 7. 总结
JVM 是 Java 工程师从“会写业务代码”走向“能治理线上系统”的关键知识。真正掌握 JVM,不是记住每个参数,而是能解释一个 Java 程序如何被加载、如何分配内存、如何执行、如何回收、如何诊断,以及在不同业务目标下如何做取舍。