JVM基础:Java 虚拟机模型
Contents
Java 虚拟机(Java Virtual Machine,JVM)是 Java 技术体系的核心。它屏蔽了底层硬件和操作系统的差异,实现了“一次编写,到处运行”(Write Once, Run Anywhere)的跨平台特性。要想深入掌握 Java 性能优化、排查线上问题,理解 JVM 的内部结构是必不可少的一环。
一、JVM 架构总览
JVM 是一种基于堆栈的虚拟机,主要由以下几个模块组成:
- 类加载子系统(Class Loader Subsystem)
- 运行时数据区(Runtime Data Areas)
- 执行引擎(Execution Engine)
- 本地接口(Native Interface)
- 垃圾回收系统(Garbage Collector)
下图是 JVM 的核心架构图:
┌────────────┐
│ ClassLoader│
└─────┬──────┘
↓
┌──────────────────────────┐
│ Runtime Data Area │
│ ┌────────────┬─────────┐│
│ │Method Area │ Heap ││
│ └────┬───────┴────┬────┘│
│ ↓ ↓ │
│ ┌────────┐ ┌──────────┐ │
│ │PC Reg. │ │Stack Frame││
│ └────────┘ └──────────┘ │
└──────────────────────────┘
↓
┌─────────────────┐
│ Execution Engine│
└─────────────────┘
↓
┌─────────────────┐
│ Native Interface│
└─────────────────┘
↓
┌─────────────────┐
│ Native Libraries│
└─────────────────┘
二、类加载子系统
类加载子系统负责从 .class 文件中读取字节码,并将其加载到内存中。加载的过程包括:
- 加载(Loading)
- 验证(Verification)
- 准备(Preparation)
- 解析(Resolution)
- 初始化(Initialization)
类加载器的类型:
- 启动类加载器(Bootstrap ClassLoader):加载
rt.jar等核心类库。 - 扩展类加载器(Extension ClassLoader):加载
jre/lib/ext目录下的类。 - 应用类加载器(App ClassLoader):加载 classpath 下的类。
类加载机制遵循双亲委派模型,防止核心类被篡改。
三、运行时数据区
JVM 在运行时会划分出多个内存区域,用于存放不同类型的数据。
1. 方法区(Method Area)【共享】
- 存储类信息、常量池、字段、方法数据、JIT 编译后的代码等
- 在 HotSpot 中,1.8 之前由永久代(PermGen)实现,1.8 起被元空间(Metaspace)替代
2. 堆(Heap)【共享】
- 所有对象实例及数组的内存分配区
- 是垃圾回收的主要区域(Young、Old)
- 分代收集策略常见:新生代(Eden、Survivor)、老年代、永久代/元空间
3. Java 虚拟机栈(Java Stack)【线程私有】
- 每个线程有独立的栈,存储栈帧(方法调用信息)
- 包含局部变量表、操作数栈、动态链接、方法返回地址等
- 如果栈空间不足可能抛出 StackOverflowError
4. 本地方法栈(Native Method Stack)【线程私有】
- 与 Java 栈类似,用于执行本地方法(Native 方法)
- HotSpot 虚拟机中 Java 栈和本地方法栈可以合并实现
5. 程序计数器(PC Register)【线程私有】
- 指示当前线程执行的字节码指令地址
- 每个线程一个独立的程序计数器,是线程切换的依据
四、执行引擎
执行引擎负责将字节码“翻译”为机器指令并执行:
核心组件:
解释器(Interpreter):逐条解释执行字节码,启动速度快但效率低。
即时编译器(JIT Compiler):将热点代码编译为机器码,提高执行效率。
- 包括 C1(Client) 和 C2(Server)两种编译器。
- 可通过
-XX:+PrintCompilation查看 JIT 编译情况。
五、垃圾回收(GC)
JVM 使用 GC 自动管理内存。常见的垃圾收集器包括:
- Serial:单线程收集,适合小应用。
- Parallel(吞吐量优先):多线程收集,适合后台任务。
- CMS(低停顿):并发标记清除,适合响应时间敏感场景。
- G1:按 Region 管理,均衡延迟与吞吐量,JDK 9 起推荐。
- ZGC / Shenandoah:低延迟收集器,适合大内存、低延迟场景。
可以通过如下参数控制 GC 行为:
-XX:+UseG1GC
-XX:+PrintGCDetails
-Xmx4g -Xms4g
六、本地接口(Native Interface)
Java 有时需要调用操作系统底层函数或 C/C++ 写的库(如图形界面、IO 操作)。JVM 提供 JNI(Java Native Interface)机制,实现 Java 和本地代码的交互。