Java类加载器
0x00 什么是类加载器
在Java中,类加载器(ClassLoader)是负责将.class文件或其他形式的字节码数据加载到Java虚拟机(JVM)中,并定义生成相应类的方法。Java的类加载器遵循双亲委派模型,它负责从不同的来源加载类,包括本地文件系统、网络等。
0x01 类加载器的作用
将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口
0x02 什么是类缓存
标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象。
0x03 类的加载器类型
引导类加载器
Bootstrap Class Loader,也称为根加载器,负责加载Java的核心类库,如rt.jar
等。它是虚拟机的一部分,由C++实现,并不是一个Java类。该加载器无法直接获取。
扩展类加载器
Extension Class Loader,负责加载Java扩展库,位于<JAVA_HOME>/lib/ext
目录下的jar包。它是由Java编写的。
应用类加载器
Application Class Loader,也称为系统类加载器,负责加载应用程序的类。它是ClassLoader类的子类,并由Java编写。也是最常用的加载器。
获取类加载器
1 | public class TestClassLoader { |
- 输出
1 | sun.misc.Launcher$AppClassLoader@18b4aac2 |
0x04 双亲委派机制
当一个类加载器收到加载请求时,它首先将加载任务委派给其父类加载器进行尝试。只有当父加载器无法加载时,才由当前类加载器
自己来尝试加载。这种层次结构保证了类的安全性和隔离性。如果自定义类加载器想要打破这个模型,可以覆盖加载逻辑。
特点:
- 每个 class 都有对应的 ClassLoader
- 除了 Bootstrap ClassLoader,每个 ClassLoader 都有一个 Parent ClassLoader
- 对于一个类加载的请求,总是先委派给 Parent ClassLoader 来进行加载
- 对于用户自定义的类加载器,默认的 Parent ClassLoader 是 AppClassLoader
0x05 类的加载过程
- 加载
将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象。
- 链接
将Java类的二进制代码合并到JVM的运行状态之中的过程。
验证:
确保加载的类信息符合JVM规范,没有安全方面的问题。
准备:
正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配。
解析:
虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程。
- 初始化
执行类构造器
当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化。
虚拟机会保证一个类的