JVM 类加载机制

JVM 类加载机制详解

JVM(Java Virtual Machine,Java 虚拟机)中的类加载机制 (Class Loading Mechanism)是指 JVM 在运行时动态加载 .class 文件,并将其转换为 JVM 识别的类对象 (Class Object),以便执行。Java 的类加载采用按需加载 (Lazy Loading)和双亲委派模型(Parent Delegation Model),确保类的安全性和避免重复加载。


1. 类加载的过程

Java 类的加载过程主要分为 五个阶段

  1. 加载(Loading)
  2. 连接(Linking)
    • 验证(Verification)
    • 准备(Preparation)
    • 解析(Resolution)
  3. 初始化(Initialization)
  4. 使用(Using)
  5. 卸载(Unloading)

(1)加载(Loading)

类加载 阶段,JVM 通过类加载器 (ClassLoader)从字节码文件.class)或其他来源(如网络、JAR包等)读取二进制数据,转换成方法区 (Method Area)中的类对象

  • 加载的来源:

    • 本地 .class 文件
    • Jar 包
    • 网络(远程加载)
    • 动态代理生成的类
    • 其他自定义数据源
  • 主要任务:

    • 通过 类加载器 读取 .class 文件,生成二进制字节流
    • 将字节流解析为 JVM 内部数据结构,存放在方法区
    • 堆区 (Heap)中生成该类的 Class 对象,用于管理该类的元数据。

示例:手动触发类加载

复制代码
Class<?> clazz = Class.forName("com.example.MyClass"); // 反射触发类加载

(2)连接(Linking)

连接是把已经加载的类转换成可以运行的状态,包括三步

  1. 验证(Verification) :确保 .class 文件格式正确,符合 JVM 规范,避免恶意字节码。
  2. 准备(Preparation) :为类变量static 变量)分配内存,并初始化默认值(不执行赋值操作)。
  3. 解析(Resolution) :把类中的符号引用转换为直接引用(指向方法区中具体的内存地址)。

示例:准备阶段

复制代码
public class Example {
    static int x = 10; // x 的默认值在准备阶段是 0,初始化阶段才会变为 10
}

(3)初始化(Initialization)

类初始化是执行静态代码的过程:

  • 执行 static 变量的赋值静态代码块static {})。
  • 初始化的顺序 按类的继承关系 从父类到子类 依次进行。

示例:类初始化

复制代码
class Parent {
    static int a = 1;
    static { System.out.println("Parent 初始化"); }
}
class Child extends Parent {
    static int b = 2;
    static { System.out.println("Child 初始化"); }
}
public class Test {
    public static void main(String[] args) {
        System.out.println(Child.b);
    }
}

输出:

复制代码
Parent 初始化
Child 初始化
2

说明

  • Parent 先初始化,因为 Child 继承自 Parent
  • 只有 static 变量和 static 代码块才会在类初始化阶段执行。

(4)使用(Using)

类初始化完成后,就可以正常使用该类:

  • 创建对象
  • 调用静态方法
  • 访问静态变量

(5)卸载(Unloading)

类在以下情况下会被卸载:

  • 类的所有实例都被 GC
  • ClassLoader 被 GC
  • JVM 关闭

但是,JVM 不会卸载 Bootstrap ClassLoader 加载的类 (即 rt.jar 内的核心类)。


2. Java 类加载器(ClassLoader)

类加载器 负责将 .class 文件加载到 JVM。JVM 主要有三种类加载器:

类加载器 作用 负责加载的类
Bootstrap ClassLoader 启动类加载器 Java 核心类库(rt.jar
Extension ClassLoader 扩展类加载器 ext 目录下的 JAR
Application ClassLoader 应用类加载器 classpath 下的类

示例:查看类加载器

复制代码
System.out.println(String.class.getClassLoader()); // null (Bootstrap 加载)
System.out.println(Test.class.getClassLoader());   // AppClassLoader

此外,Java 支持 自定义类加载器

示例:自定义 ClassLoader

复制代码
class MyClassLoader extends ClassLoader {
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] bytes = loadClassData(name); // 自定义加载逻辑
        return defineClass(name, bytes, 0, bytes.length);
    }
}

3. 双亲委派机制(Parent Delegation Model)

工作原理

当一个 ClassLoader 需要加载类时,它不会直接加载,而是:

  1. 先委托给父类加载器。
  2. 父类加载失败(即找不到类)时,才会由子类加载器尝试加载。

作用

  • 避免重复加载 :防止 Java 核心类(如 java.lang.String)被自定义类覆盖。
  • 提高安全性:防止恶意代码篡改 Java 标准库。

示例:双亲委派

复制代码
public class Test {
    public static void main(String[] args) {
        System.out.println(Test.class.getClassLoader()); // AppClassLoader
        System.out.println(String.class.getClassLoader()); // null (Bootstrap)
    }
}

4. 类的主动引用 & 被动引用

(1)主动引用(会触发类加载)

以下情况会触发类加载:

  • 创建对象new 关键字)
  • 访问静态变量
  • 调用静态方法
  • 反射
  • 子类初始化时,会先加载父类

示例:主动引用

复制代码
class Parent {
    static { System.out.println("Parent 被加载"); }
}
public class Test {
    public static void main(String[] args) {
        Parent p = new Parent(); // 触发加载
    }
}

(2)被动引用(不会触发类加载)

  • 通过子类访问父类的静态变量
  • 访问 final 常量
  • Class.forName() 的 initialize=false 方式

示例:被动引用

复制代码
class Parent {
    static { System.out.println("Parent 被加载"); }
    static int a = 10;
}
class Child extends Parent {}
public class Test {
    public static void main(String[] args) {
        System.out.println(Child.a); // 仅加载 Parent
    }
}

总结

  1. 类加载分为:加载、连接(验证、准备、解析)、初始化、使用、卸载。
  2. JVM 采用双亲委派机制,确保安全性和避免重复加载。
  3. 主动引用会触发类加载,被动引用不会

JVM 类加载机制是 Java 运行时的核心之一,理解它有助于优化内存管理和类加载行为。

相关推荐
小张成长计划..9 分钟前
【C++】16:模板进阶
c++·算法
AndrewHZ11 分钟前
【图像处理基石】如何使用大模型进行图像处理工作?
图像处理·人工智能·深度学习·算法·llm·stablediffusion·可控性
AndrewHZ15 分钟前
【图像处理基石】图像处理的基础理论体系介绍
图像处理·人工智能·算法·计算机视觉·cv·理论体系
爱笑的眼睛111 小时前
PyTorch Lightning:重新定义深度学习工程实践
java·人工智能·python·ai
Kevinyu_1 小时前
责任链模式
java·hadoop·责任链模式
明洞日记1 小时前
【设计模式手册012】责任链模式 - 请求处理的流水线艺术
java·设计模式·责任链模式
q***07141 小时前
Java实战:Spring Boot application.yml配置文件详解
java·网络·spring boot
雨中飘荡的记忆2 小时前
Spring Alibaba AI 实战指南
java·ai编程
冰封剑心2 小时前
MiniCPM-V-2_6 (4-bit 量化)使用
java·前端·数据库
mqiqe2 小时前
【Spring AI MCP】四、MCP 服务端
java·人工智能·spring