Java基础 - JVM

什么是JVM

Java的理念是:Write Once, Run Anywhere。Java编译器把 Java 程序编译成“字节码”(.class 文件),字节码可以在所有平台运行,这是JAVA特性之一。字节码是 JVM 能理解的“中间语言”,JVM可以把字节码翻译成你的电脑能理解的机器指令。因此只需要在不同的机器上安装适配不同架构的JVM,就可以实现 Write Once, Run Anywhere。

JVM的功能

  • 跨平台运行
  • 内存管理:JAVA帮助开发者垃圾回收,分配内存
  • 性能优化:即时编译器(Just-In-Time ,JIT ),将热点代码(频繁执行的代码段)编译成本地机器码,以提高程序的执行性能
  • 安全性:异常处理,类加载时字节码验证,沙箱环境等

JVM的运行时数据区域

以JDK 1.7为例,

  • 线程私有的:
    • 程序计数器:当前线程执行的字节码位置
    • Java 虚拟机栈:每个线程的JAVA方法的“方法调用栈”,包含栈帧
    • 本地方法栈:给调用 C、C++ 等非 Java 方法(native 方法)用的栈
  • 线程共享的
    • 堆:用来存储所有 Java 对象实例,由垃圾回收器(GC)统一管理
    • 方法区:用来存储类的元数据(类的信息、常量、静态变量、方法字节码等)。

类加载器

类加载器是指把类的字节码(通常是 .class 文件)加载到 JVM 的内存中,并生成相应的 Class 对象的工具。具体来说,类加载器把字节码(.class 文件)加载到 JVM 的方法区(Method Area)(Java 8 之后是 元空间(Metaspace)),然后在堆中创建一个 Class 对象来存储类的信息,方便反射操作。

类并不是一开始就全部加载。类加载器可以按需加载:当你第一次使用某个类时,它才去加载它。

public class Person {
    static List<String> list = new ArrayList<>();

    static {
        System.out.println("Person 类被初始化");
    }

    int age = 20;

    public void sayHello() {
        System.out.println("Hello");
    }
}

根据以上的例子,类加载器执行过程:

  1. 加载:类加载器通过类的名字 Person 找到 Person.class 文件,将 .class 文件的字节码加载到 JVM,并在堆中生成一个代表这个类的 java.lang.Class 对象作为数据访问的入口
  2. 验证:检查字节码是否合法
  3. 准备:为静态变量(List<String> list)分配内存,并赋初始值 null(此时静态变量只是占位,还没初始化)
  4. 解析:将符号引用替换为直接引用,比如将System.out.println方法名解析为真正的内存地址
  5. 初始化:执行静态代码块,给静态变量赋值(这里的list变量本身在方法区,指向的HashMap对象实例在堆里创建)

Class对象

public final class Class {
    private Class() {}
}

比如,当JVM加载String类时,会执行Class cls = new Class(String);在堆中创建Class对象。这个对象包含类名、包名、父类、实现的接口、所有方法、字段等对应class的所有信息。内存分布:

Java 堆:
┌────────────────────────────┐
│ Class<Person> clazz        │
│ ── name: "Person"          │
│ ── loader: AppClassLoader  │
│ ── klass_pointer →────────────┐
└────────────────────────────┘  │
                                |
方法区(Metaspace):              ▼
┌────────────────────────────┐
│ Class Metadata (Klass*)    │
│ ── className: "Person"     │
│ ── superClass: java.lang.Object
│ ── interfaces: ...         │
│ ── methods[]: sayHello()   │
│ ── fields[]: name          │
│ ── constantPool: ...       │
│ ── annotations: ...        │
└────────────────────────────┘

JAVA对象在内存中的结构

  1. 对象头
    包含:
  • 标记字段(Mark Word):指向哈希码(HashCode)、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程 ID等。
  • 类型指针(Klass pointer):指向类的元数据,是一个在方法区的C++结构,与上文Class对象的klass_pointer指向的结构一样。
  1. 实例数据
  2. 对齐填充

Java基础 - JVM
http://example.com/2025/07/04/JAVA_basis/java-jvm/
Author
Songlin Zhao
Posted on
July 4, 2025
Licensed under