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 对象来存储类的信息,方便反射操作。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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对象

1
2
3
public final class Class {
private Class() {}
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
https://thiefcat.github.io/2025/07/04/JAVA/java-jvm/
Author
小贼猫
Posted on
July 4, 2025
Licensed under