Contents

JVM基础:Java 虚拟机模型

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 和本地代码的交互。