一、怎样理解类加载机制

当程序运行时,JVM 会把 .class 字节码文件 从磁盘 / 网络 / 其他位置加载到内存,并进行验证、准备、解析、初始化,最终变成可以直接使用的 Java 类型,这个全过程就是 类加载机制

简单说:把 class 文件变成内存中可用的类 = 类加载

二、类加载机制的生命周期

类加载机制分为3个阶段:Loading、Linking(验证、准备、解析)、Initialization‌。

完整的生命周期一共 7 个阶段,前 5 个是类加载过程

1. 加载(Loading)

JVM 做三件事:

  • 通过全类名获取 class 文件的二进制字节流
  • 将字节流转化为方法区的运行时数据结构
  • 在内存中生成一个 java.lang.Class 对象(作为访问入口)

加载来源:本地文件、JAR、网络、动态生成等。

2. 验证(Verification)

保证 class 文件符合 JVM 规范、不会危害虚拟机安全。包括:

  • 文件格式验证
  • 元数据验证
  • 字节码验证
  • 符号引用验证

3. 准备(Preparation)

为类的静态变量分配内存,并设置默认初始值

注意:

  • 只给静态变量分配
  • 赋的是默认零值,不是代码里写的值
  • final static 常量会直接赋值
public static int a = 10;

准备阶段:a = 0(默认值); 初始化阶段:a = 10

4. 解析(Resolution)

符号引用替换成直接引用。简单理解:把 “类名 / 方法名 / 字段名” 变成真正的内存地址。

5. 初始化(Initialization)

类加载最核心的阶段。执行:

  • 静态变量赋值
  • 静态代码块 static{}

什么时候才会触发初始化?只有以下 6 种情况会触发:

  • new 对象
  • 访问 / 设置静态变量
  • 调用静态方法
  • 反射(Class.forName ())
  • 初始化子类时,父类先初始化
  • 程序运行主类(含 main 方法的类)

6. 使用(Using)

7. 卸载(Unloading)

满足三个条件:

  • 该类的所有实例都被 GC
  • 该类的 Class 对象没有任何引用
  • 类加载器已被回收

三、类加载器

1. 三层类加载器(Java 默认)

JVM 不直接加载类,而是交给类加载器。类加载器的顺序是从上到下

  • 启动类加载器(Bootstrap):加载JAVA_HOME/lib 核心类(如 String、Integer),顶层。
  • 扩展类加载器(Extension):加载JAVA_HOME/lib/ext
  • 应用类加载器(Application):加载用户类路径(classpath)下的类,包括开发者编写的类和第三方库
  • 自定义类加载器(Custom ClassLoader):根据特定需求自定义类加载逻辑

2. 类加载的三个重要特性

  • 全盘负责:加载一个类时,它依赖的所有类也由同一个加载器加载
  • 双亲委派
  • 缓存机制:加载过的类会缓存,下次直接用,不用重新加载

四、双亲委派机制

1. 双亲委派模型(最重要机制)

机制规则:

  • 类加载时,先交给父加载器
  • 父加载器找不到,再自己加载
  • 永远不优先自己加载

目的:

  • 安全:防止核心类被篡改
  • 唯一性:保证一个类在 JVM 中只加载一次
  • 避免类混乱:保证基础类统一,不会出现多个版本冲突

2. 双亲委派流程

  • 类加载器收到请求,先检查是否已加载。
  • 未加载 → 委托父加载器,一直向上到启动类加载器。
  • 顶层加载器能找到 → 直接加载。
  • 找不到 → 依次退回给子类加载器尝试加载。
  • 都找不到 → 抛出 ClassNotFoundException

3. 打破双亲委派机制

重写 ClassLoaderloadClass() 方法,不按照默认的向上委托逻辑执行,直接自己加载类,就打破了双亲委派。

PS:(1) findClass():真正查找类文件的方法,自定义加载器时重写它。

         (2) 想遵守双亲委派 → 重写 findClass();想打破双亲委派 → 重写 loadClass()

打破双亲委派机制的场景:

  • SPI服务发现机制(如JDBC,JDBC 接口由启动类加载器加载,但实现类在项目目录里,启动类加载器找不到。所以需要线程上下文类加载器反向委托子类加载,这就破坏了双亲委派
  • Tomcat 容器(打破原因:同一个服务器上不同 Web 应用使用不同版本的类库(如 Spring);应用之间相互隔离,互不影响。)
  • OSGi 模块化 = 面向 Java 的动态模块化框架(OSGi 每个模块(Bundle)都有自己独立的类加载器,允许程序拆分为可独立安装、启动、卸载的模块,实现热部署和类隔离。)

4. 类加载机制与双亲委派模型

Java类加载机制遵循“双亲委派模型”(Parent Delegation Model),该模型规定了类加载器之间的层次关系和类加载顺序。

    Logo

    AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

    更多推荐