JVM — Java 虚拟机内核

Java 的”操作系统”——类加载器、字节码解释器、分层编译、高级 GC、JNI 桥接。

概念

HotSpot JVM 是 Java 平台的旗舰实现,用 C++ 编写。JVM 不仅仅是一个解释器——它是一整套运行时环境:从 class 文件验证到类加载,从解释执行到 C1/C2 JIT 编译,从分代 GC 到 JNI 本地调用。JVM 是”托管运行时”的典范,也是 Rust/Go 运行时设计的参考对象。

核心组件

组件职责关键机制
类加载器查找、加载、链接 class 文件双亲委派模型
字节码解释器执行 class 文件中的字节码指令栈帧模型
C1 编译器快速 JIT (Client Compiler), 低延迟线性扫描寄存器分配
C2 编译器优化 JIT (Server Compiler), 高峰值性能图着色寄存器分配
对象模型Mark Word + Klass pointer + 字段 + 对齐对象头
G1GC / ZGC分代 + 并发 + 低停顿 GC分区、染色指针
JNIJava 调用 C/C++ 代码的桥梁native 方法调用

类加载器层次

Bootstrap ClassLoader (加载核心库)
      ^                   rt.jar / modules 中的 java.lang.*, java.util.*
      |
Extension ClassLoader    (JDK 8 及之前, 加载 jre/lib/ext)
      ^
      |
Application ClassLoader  (加载 classpath 中的用户类)

双亲委派模型: 每个类加载器收到加载请求时,先委托给父加载器,父加载器找不到才自己加载。这保证了核心类不会被用户代码篡改。

对象头布局 (64-bit JVM)

+------------------------+------------------------+------------------------+------------------------+
|   Mark Word (64-bit)   |  Klass Pointer (32-bit  |  Instance Fields...    |  Padding               |
|                        |  with compressed oops) |                        |  (to 8-byte alignment) |
+------------------------+------------------------+------------------------+------------------------+
| bits [0:1] = lock flag                                                                    |
|   01: unlocked / biased                                                                   |
|   00: lightweight locked                                                                  |
|   10: heavyweight locked                                                                  |
|   11: GC mark                                                                             |
| bits [25:31] = identity hashcode (on demand)                                              |
| bits [32:62] = age (GC 分代年龄)                                                           |

C1 → C2 分层编译

mermaid
graph TD
    L0["Level 0: 解释执行<br/>纯字节码解释器"]
    L1["Level 1: C1 无 profile<br/>简单 C1 编译, 无收集数据"]
    L2["Level 2: C1 有限 profile<br/>快速编译, 收集部分类型数据"]
    L3["Level 3: C1 完整 profile<br/>完整编译, 收集所有调用/分支数据"]
    L4["Level 4: C2 编译<br/>基于 profile 的深度优化"]

    L0 --> L3
    L0 --> L2
    L2 --> L3
    L3 --> L4
    L4 --> L0

    style L0 fill:#f9f,stroke:#333
    style L4 fill:#9f9,stroke:#333

G1GC 概览

阶段描述是否并发
初始标记 (Initial Mark)标记 GC Roots 直接可达对象STW (短)
并发标记 (Concurrent Mark)从 roots 出发并发追踪引用图并发
最终标记 (Remark)处理并发标记期间的修改STW (短)
清除 (Cleanup)计算区域存活度, 挑选回收区域STW (短)
复制 (Evacuation)将存活对象复制到新区域, 回收旧区域STW (并行)

JNI 桥接

Java (JavaVM)
  |
  |  System.loadLibrary("native")
  |  native int compute(int a, int b);
  |                      |
  |    JNIEXPORT jint JNICALL Java_com_example_Main_compute
  |    (JNIEnv *env, jobject obj, jint a, jint b) {
  |        return a + b;
  |    }
  |
C/C++ (libnative.so / native.dll)

JNI 调用开销: ~10-40ns (直接调用) 或 ~200ns+ (需要类型转换)。JNI 临界区会阻止 GC 移动正在使用的对象。