序言
简单学习下ClassLoad的过程cuiyaonan2000@163.com
过程
我们有一个x.java文件通过执行javac命令可以变成x.class文件,当我们调用Java命令的时候class文件会被装载到内存中,这个过程叫做classloader。
一般情况下我们自己写代码的时候会用到Java的类库,所以在加载的时候也会把Java类库相关的类也加载到内存中。装载完成之后会调用字节码解释器和JIT即时编译器来进行解释和编译,编译完之后由执行引擎开始执行,执行引擎下面对应的就是操作系统硬件了。
执行引擎就会把解释和编译后的代码转换成硬件所能理解的语言区执行了cuiyaonan2000@163.com
类加载器种类
BootstrapClassLoader 系统类加载器
BootstrapClassLoader并非java代码实现的,而是由C/C++代码编写的,它本身属于虚拟机的一部分,主要负责加载Java标准库的一些类,如 java.lang 包等,这些类通常位于 JDK 的 jre/lib 目录下。
ExtClassLoader 扩展类加载器/PlatformClassLoader 平台类加载器
负责加载Java扩展库的类,这些类通常位于JDK 的 jre/lib/ext目录下,在 Java 9 之后,由于模块化的引入,这个类加载器已经被废弃。
平台类加载器负责加载 JDK 自带的模块。这些模块通常位于 JDK 安装目录下的 jmods
文件夹中
APPClassLoader 系统类加载器
AppClassLoader 主要加载系统属性“java.class.path”配置下类文件,也就是环境变量 CLASS_PATH 配置的路径。因此 AppClassLoader 是面向用户的类加载器,我们自己编写的代码以及使用的第三方 jar 包通常都是由它来加载的。
双亲委派模式(Parents Delegation Model)
既然 JVM 中已经有了这 3 种 ClassLoader,那么 JVM 又是如何知道该使用哪一个类加载器去加载相应的类呢?答案就是:双亲委派模式。
双亲委派模式(Parent Delegation Model)是 Java 类加载器体系中的一种设计模式。它描述了类加载器在加载类时应如何与其父加载器(parent class loader)进行协作。双亲委派模式可以确保类在加载过程中的安全性和避免多次加载同一个类。
双亲委派模式的工作原理如下:
- 当一个类加载器(ClassLoader)被要求加载一个类时,它首先会将加载请求委托给其父类加载器。
- 父类加载器会递归地将加载请求继续委托给它自己的父类加载器,直到请求到达启动类加载器(Bootstrap ClassLoader)。
- 启动类加载器会检查它是否能够加载该类。如果可以加载,它将加载这个类并返回;否则,它会将加载请求传递回给子加载器。
- 子加载器会检查它是否能够加载该类。如果可以加载,它将加载这个类并返回;否则,它会将加载请求传递回给下一个子加载器。
- 如果所有加载器都无法加载该类,那么
ClassNotFoundException
将被抛出。
双亲委派模式的优势:
- 避免类的重复加载:由于每个加载器只会尝试加载它的父加载器无法加载的类,这样可以确保同一个类不会被多次加载。
- 保护 Java 核心类库的安全性:由于启动类加载器是第一个尝试加载类的加载器,用户自定义的类加载器无法加载 Java 核心类库中的类。这可以防止核心类库被恶意代码篡改或替换。
- 有助于实现类的隔离:使用不同的类加载器可以实现类的隔离,这对于应用服务器等场景非常有用,因为它们需要隔离不同应用之间的类加载。