类的加载
类加载
Java类加载的三个阶段
- 加载(Loading)
把类的字节码读进内存,创建Class对象。 - 链接(Linking)
验证字节码、准备静态变量的内存空间(默认赋初值)。 - 初始化(Initialization)
执行类的静态代码块和静态变量的显式赋值。
Java 类加载器(ClassLoader)负责查找和加载类的字节码到 JVM 中。它们按照一定的顺序和规则进行加载,以确保类的唯一性和安全性。
类加载机制
类加载与反序列化
- 类加载时,JVM会执行类的静态代码块(初始化阶段)
- 实例化对象时会执行构造代码块和无参构造函数(实例化阶段)
- 反序列化通常会触发类加载,因此静态代码块可能会被执行,这也是反序列化安全隐患的一个重要原因
动态类加载方法
Class.forName()可以加载类,并且默认会执行类的初始化(静态代码块,可以选择初始化和不初始化ClassLoader.loadClass()只加载类但不初始化,即不会执行静态代码块,通常需要调用Class.forName或手动初始化才能执行静态代码块
| 代码块类型 | 什么时候执行 |
|---|---|
| 静态代码块(static) | 类加载时执行,只执行一次 |
| 构造代码块 | 每次创建对象时执行 |
| 构造方法 | 每次创建对象时执行,紧跟实例初始化块后 |
1 | |

加载类和实例化类的区别
加载类
把类的字节码从文件(比如 .class 文件)或者其他地方读进内存,JVM 会为这个类创建一个 Class 对象。
实例化类
根据加载好的类,创建该类的一个对象(实例)。
Class.forName(String className)和ClassLoader.loadClass(String className)的区别
Class.forName(String className)
加载指定类,并且会对类进行初始化(执行静态代码块)。
ClassLoader.loadClass(String className)
加载指定类,但不会执行初始化,只是把类加载到JVM中。
加载方式
URLClassLoader → 从 URL 位置(文件、HTTP、JAR)加载现成的类文件。
ClassLoader.defineClass → 用字节数组加载类(需要继承 ClassLoader 调用)。
Unsafe.defineClass → 直接用字节数组加载类(更底层,但 public 类有包名限制)。
ClassLoader的分类
- Bootstrap ClassLoader:这是最顶层的类加载器,通常由本地代码实现,负责加载位于
<JAVA_HOME>/lib目录下的核心Java库。 - Extension ClassLoader:作为Bootstrap ClassLoader的子类加载器,它负责加载扩展库中的类,即位于
<JAVA_HOME>/lib/ext目录下的类。 - Application ClassLoader:也称为System ClassLoader,它是Extension ClassLoader的子类加载器,负责加载应用类路径上指定的所有类(包括用户定义的类和第三方库)。
- Custom ClassLoader:开发者可以根据需要创建自己的类加载器,这些自定义类加载器通常继承自
java.lang.ClassLoader,并可用于从非标准位置加载类,支持动态加载、热替换等功能。
ClassLoader的加载机制
1 | |
当这三者中的某个ClassLoader要加载一个类时,会先委托它的父类加载器尝试加载,一直往上,如果最顶级的父类加载器没有找到该类,那么委托者则亲自到特定的地方加载

Java 类在使用前必须被编译到类路径下,JVM 通过双亲委派机制的类加载器,从类路径中加载字节码,完成类的加载、链接和初始化。
- 请求到达App ClassLoader:
- 当应用程序需要加载某个类时,首先会将这个请求传递给应用程序类加载器(App ClassLoader)。
- 委托给Extension ClassLoader:
- App ClassLoader不会立即尝试自己加载这个类,而是先将这个请求委托给它的父类加载器——扩展类加载器(Extension ClassLoader)。
- 委托给Bootstrap ClassLoader:
- Extension ClassLoader同样不会立即尝试自己加载这个类,而是继续将请求委托给它的父类加载器——启动类加载器(Bootstrap ClassLoader)。
- Bootstrap ClassLoader尝试加载:
- Bootstrap ClassLoader检查是否能在其负责的范围内找到并加载该类(即在核心Java库中查找)。如果找到了,则完成加载;如果没有找到,则返回“未找到该类”的结果。
- 回退到Extension ClassLoader:
- 如果Bootstrap ClassLoader未能找到该类,控制权会回到Extension ClassLoader。此时,Extension ClassLoader会在其负责的范围内(即扩展库目录)查找并尝试加载该类。如果找到了,则完成加载;如果没有找到,则再次返回“未找到该类”的结果。
- 最终由App ClassLoader加载:
- 如果Bootstrap ClassLoader和Extension ClassLoader都无法加载该类,那么最后的尝试就落在了App ClassLoader身上。App ClassLoader会在用户定义的类路径上查找并加载该类。如果在这个过程中找到了该类,则完成加载;如果仍然找不到,则会抛出
ClassNotFoundException异常。
- 如果Bootstrap ClassLoader和Extension ClassLoader都无法加载该类,那么最后的尝试就落在了App ClassLoader身上。App ClassLoader会在用户定义的类路径上查找并加载该类。如果在这个过程中找到了该类,则完成加载;如果仍然找不到,则会抛出
自定义ClassLoader
1、为什么要自定义ClassLoader
因为系统的ClassLoader只会加载指定目录下的class文件,如果你想加载自己的class文件,那么就可以自定义一个ClassLoader.
而且我们可以根据自己的需求,对class文件进行加密和解密。
2.如何自定义ClassLoader
- 新建一个类继承自java.lang.ClassLoader,重写它的findClass方法。
- 将class字节码数组转换为Class类的实例
- 调用loadClass方法
类的加载
http://xiaowu5.cn/2025/12/04/类的加载/