源本科技 | 码上会

JVM 工作原理

2025/12/22
18
0

引言

Java 虚拟机(JVM)是 Java 运行时环境(JRE)的核心组件,它使 Java 程序无需修改即可在任何平台上运行。JVM 充当 Java 字节码与底层硬件之间的解释器,从而实现了 Java 著名的“一次编写,到处运行”(Write Once, Run Anywhere,WORA)特性

  • Java 源代码(.java) → 由 javac 编译 → 字节码(.class)

  • JVM 加载字节码,对其进行验证和链接,然后执行

  • 执行过程可能包括直接解释字节码,或通过即时编译(Just-In-Time, JIT)将频繁执行的“热点”代码编译为本地机器码以提升性能

  • 垃圾回收机制在后台自动运行,回收不再使用的对象所占用的内存

JVM 架构

  • 类加载子系统(Class Loader Subsystem)

  • 运行时数据区域(Runtime Data Areas)

  • 执行引擎(Execution Engine)及其相关组件

Class Files

  • 输入来源.class 文件,Java 源代码经过编译后生成的字节码文件(即 .class 文件),是 JVM 的输入

  • 流向:箭头从 “Class Files” 指向 “Class Loader Subsystem”,表示这些文件首先被类加载器处理

作用:类加载子系统负责将 .class 文件加载到 JVM 内存中,并完成后续的链接和初始化过程

类加载子系统

Class Loader Subsystem 位于顶部,是 JVM 启动时第一个工作的模块。它与下方的 “运行时数据区域” 之间有双向箭头,表示两者存在交互

职责

  • 加载 .class 文件

  • 验证字节码安全性

  • 准备静态变量内存空间

  • 解析符号引用

  • 初始化类(执行静态块、赋值静态变量)

与运行时数据区域的关系

  • 将类信息写入 Method Area

  • 创建 Class 对象并放入 Heap

  • 为静态变量分配空间(在 Method Area 中)

运行时数据区域

这是一个大的矩形框,代表 JVM 在程序运行期间使用的内存区域。包含以下五个部分:

方法区

Method Area

  • 存储类的元数据:类名、父类、接口、方法、字段、常量池等

  • 所有线程共享

  • 类似于永久代(PermGen)或元空间(Metaspace,JDK 8+)

Heap

  • 存放所有对象实例(通过 new 创建)

  • 是垃圾回收的主要区域

  • 所有线程共享

Java 线程

Java Threads

  • 表示 JVM 中创建的所有用户线程

  • 每个线程拥有自己的 虚拟机栈(Stack)程序计数器(PC Register)

  • 负责执行 Java 方法

程序计数器寄存器

Program Counter Registers

  • 每个线程一个独立的 PC 寄存器

  • 记录当前线程正在执行的字节码指令地址

  • 是唯一不会抛出 OutOfMemoryError 的内存区域

本地内部线程

Native Internal Threads

  • 用于支持本地方法调用(如 JNI)、GC、JIT 编译等后台任务

  • 这些线程由 JVM 自身管理,不是用户代码直接创建的

执行引擎

位于底部,是 JVM 的“大脑”,负责执行字节码。其内部包括三个关键组件:

执行引擎

Execution Engine

  • 核心执行单元,读取字节码并逐行执行

  • 通常结合解释器(Interpreter)和 JIT 编译器工作

即时编译器

JIT Compiler

  • 监控热点代码(频繁执行的方法)

  • 将热点字节码编译成本地机器码,提升性能

  • 提高了执行效率,避免重复解释

垃圾回收器

Garbage Collector

  • 自动回收不再被引用的对象所占用的堆内存

  • 属于执行引擎的一部分,但独立运行于后台线程中

  • 可以配置不同垃圾回收算法(如 G1、ZGC 等)

与运行时数据区域的关系

  • 与 Heap 和 Method Area 有双向通信,因为 GC 需要扫描堆和类元数据来判断对象是否可回收

  • JIT 编译也需要访问方法区获取方法信息

本地方法接口

Native Method Interface

  • 位于执行引擎右侧,是一个桥梁模块

  • 作用是连接 JVM 与外部本地库

  • 支持 Java 代码调用 C/C++ 编写的本地函数,反之亦然(JNI)

与执行引擎的关系:

  • 当 Java 方法调用 native 方法时,执行引擎会通过 JNI 接口传递控制权给本地方法

本地方法库

Native Method Libraries

  • 位于最右侧,表示操作系统层面的原生库(如 .dll.so.dylib

  • 包含用 C、C++ 等语言编写的底层函数

  • 例如:图形界面(AWT/Swing)、文件 I/O、网络通信等底层实现

通过 JNI 接口,JVM 可以调用这些库中的函数,从而实现对硬件或系统资源的访问

整体流程

  • Class Files → 被 Class Loader Subsystem 加载

  • 类信息存储至 Method Area,对象实例进入 Heap

  • Java Threads 开始执行,每个线程有自己的 StackPC Register

  • 执行引擎读取字节码,使用 InterpreterJIT Compiler 执行

  • 若调用 native 方法,则通过 Native Method Interface 调用 Native Method Libraries

  • Garbage Collector 定期清理无引用对象,释放堆内存

  • Native Internal Threads 协助完成 GC、JIT 等后台任务

JVM 架构关键点

JVM 的模块化设计思想:加载 → 存储 → 执行 → 优化 → 回收,确保了 Java 应用的安全性、高效性和跨平台能力

组件

功能简述

Class Loader

加载并验证类

Runtime Data Areas

存储运行时所需的数据结构(堆、栈、方法区等)

Execution Engine

执行字节码的核心引擎

JIT Compiler

提升性能,编译热点代码为本地代码

Garbage Collector

自动内存管理

JNI & Native Libraries

实现 Java 与本地代码互操作