Skip to content

JVM 知识体系

Java 虚拟机(JVM)是 Java 语言能够“一次编写,到处运行”的核心。它是一个抽象的计算机,负责将 Java 字节码翻译成特定平台的机器码并执行。理解 JVM 对于 Java 开发者来说至关重要,因为它能帮助你编写出更高效、更稳定的代码,并更好地进行性能调优和故障排查。

JVM 的主要组成部分

JVM 的架构通常可以分为以下几个关键部分:

1. 类加载系统 (Class Loading Subsystem)

类加载器负责在运行时将 .class 文件(包含字节码)加载到 JVM 内存中。它经历三个主要阶段:

  • 加载 (Loading): 查找并加载类的二进制数据到内存中。
  • 链接 (Linking):
    • 验证 (Verification): 确保加载的 .class 文件符合 JVM 规范,没有安全问题。
    • 准备 (Preparation): 为类的静态变量分配内存,并初始化为默认值。
    • 解析 (Resolution): 将字节码中的符号引用(如类名、方法名)转换为直接引用(内存地址)。
  • 初始化 (Initialization): 执行类的 <clinit>() 方法,初始化静态变量为程序员指定的值,并执行静态代码块。

JVM 中有三种主要的内置类加载器:

  • 启动类加载器 (Bootstrap ClassLoader): 负责加载 JRE/lib 目录下的核心类库。
  • 扩展类加载器 (Extension ClassLoader): 负责加载 JRE/lib/ext 目录下的扩展库。
  • 应用程序类加载器 (Application ClassLoader): 负责加载应用程序 classpath 下的类。

2. 运行时数据区 (Runtime Data Areas)

这是 JVM 在程序执行期间分配内存的区域,主要包括:

  • 程序计数器 (Program Counter Register): 一块很小的内存空间,用于存储当前线程正在执行的字节码指令地址。它是线程私有的,每个线程都有一个独立的程序计数器。
  • Java 虚拟机栈 (Java Virtual Machine Stacks): 描述 Java 方法执行的内存模型。每个方法在执行时都会创建一个栈帧 (Stack Frame),用于存储局部变量表、操作数栈、动态链接和方法出口信息。它也是线程私有的。
  • 本地方法栈 (Native Method Stacks): 与虚拟机栈类似,但它为 JVM 执行的 Native 方法服务(即由 C/C++ 等语言编写的方法)。也是线程私有的。
  • Java 堆 (Java Heap): JVM 中最大的一块内存区域,用于存储对象实例和数组。它是所有线程共享的区域,也是垃圾回收器主要管理的地方。堆通常分为新生代(Young Generation)和老年代(Old Generation)。
  • 方法区 (Method Area): 用于存储已被 JVM 加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。它是所有线程共享的区域。在 JDK 8 之后,元空间 (Metaspace) 取代了永久代(PermGen),位于本地内存而非 JVM 内存。

3. 执行引擎 (Execution Engine)

执行引擎负责执行加载到内存中的字节码。它包括:

  • 解释器 (Interpreter): 逐行解释字节码并执行,启动速度快,但执行效率相对较低。
  • 即时编译器 (Just-In-Time Compiler, JIT):
    • 热点代码 (HotSpot Code): 识别出程序中频繁执行的代码,将其编译成机器码并缓存起来。
    • 优化: 对编译后的机器码进行各种优化,提高执行效率。
    • 客户端编译器 (C1) 和 服务端编译器 (C2): 两种不同的 JIT 编译器,C1 编译速度快,优化程度低;C2 编译速度慢,但优化程度高,适用于长时间运行的服务端应用。
  • 垃圾回收器 (Garbage Collector, GC): 自动管理堆内存。它会找出不再被引用的对象并清除它们,以释放内存空间。常见的垃圾回收器包括:
    • Serial GC: 单线程、停顿一切 (Stop The World)。
    • Parallel GC: 多线程、停顿一切。
    • CMS GC: 并发标记清除,停顿时间短,但有碎片问题。
    • G1 GC: 面向服务端应用,兼顾吞吐量和停顿时间。
    • ZGC / Shenandoah: 新一代的低延迟垃圾回收器。

4. 本地方法接口 (Native Method Interface) & 本地方法库 (Native Method Libraries)

  • 本地方法接口 (JNI - Java Native Interface): 允许 Java 代码与其他语言(如 C/C++)进行交互。Java 代码可以通过 JNI 调用本地方法库中的函数,反之亦然。
  • 本地方法库: 包含用其他语言编写的、供 Java 代码调用的库。

总访问量
总访问人数 人次