Files
rikako-note/java se/classloader.md
2025-11-09 23:25:34 +08:00

75 lines
5.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Classloader
Java ClassLoader是构成JREJava Runtime Environment的一部分ClassLoader负责动态的将java classes加载到JVM中。java classes并不是一次性全部加载到内存中的而是在应用需要时动态加载到内存中。
> JRE调用classloader然后classloader负责将classes动态加载到内存中。
在java`按需将需要的类动态加载到内存中`的特性中classloader扮演了重要的作用令Java应用更加的弹性和高效。
## Types of ClassLoaders in Java
java ClassLoaders可以被归类为不同的类型每种类型负责从指定的路径加载classes
### Bootstrap ClassLoader原始类加载器
- Bootstrap Classloader是机器码负责初始化JVM的操作
- 直到java 8中其从`rt.jar`中加载核心java文件但是从java 9开始其负责从java runtime image中加载核心java文件
- Bootstrap ClassLoader独立的操作其并没有parent ClassLoader
### Platform ClassLoaderExtension ClassLoader
- 在java 9之前存在Extension ClassLoader但是在java 9及之后其被称作Platform ClassLoader
- 该classloader会从JDK module系统中加载平台特定的拓展
- platform class loader会从java runtime image中加载文件同时也会从`java.platform`属性所指定的module或`--module-path`所指定的module处加载文件
### System ClassLoaderApplication ClassLoader
- System ClassLoader也被称为`Application ClassLoader`,其从应用的classpath加载classes
- 其是Platform ClassLoader的一个child
- 将会从`CLASSPATH`环境变量、`-classpath``-cp`选项所指定的目录处加载
## Principles of Functionality of a Java ClassLoader
java ClasLoader基于如下准则进行操作
### Delegation Model
- ClassLoaders遵循委托继承算法
- 当JVM遇到一个class时其会检查其是否已经被加载如果该class还未被加载那么JVM会将class的加载委托给`a chain of ClassLoaders`
- 该委托架构从Application ClassLoader开始向上移动到Platform ClassLoader最终移动到Bootstrap ClassLoader
- 在层次结构中的每一个ClassLoader都会在其负责的locations处查找class并且在必要时将class的加载过程委托给父级
### Visibility Principle
- 由Parent ClassLoaders负责加载的classes对于child classloader来说也是可见的反之由child classloader负责加载的classes对于parent classloader来说则不可见
- 上述的可见性定义确保了封装性防止由不同的classloaders负责加载的classes出现冲突
### Uniqueness Property
- ClassLoader会确保class只会被加载一次从而保证class在JVM中的唯一性
- 只有当parent ClassLoader无法查询到某个类时当前classloader才会尝试去加载该类
## Methods of java.lang.ClassLoader
为了加载类ClassLoader中提供了如下方法
- `loadClass(String name, boolean resolve)`: 其会加载JVM所引用的类并在必要时进行解析
- `defineClass()`: 该方法会将一个字节数组转化为Class实例对象。如果字节数组中的内容不是有效的class那么将会抛出ClassFormatError异常
- `findClass(String name)`该方法会对class进行查找但是并不会对其进行加载
- `findLoadedClass(String name)`:该方法用于验证是否该类已经被加载
- `Class.forName(String name, boolean initialize, ClassLoader loader)` 该方法会加载并初始化class允许指定ClassLoader如果该classLoader没有指定则默认会使用Bootstrap ClassLoader
上述方法的使用示例如下:
```java
// Code executed before class loading
Class<?> clazz = ClassLoader.getSystemClassLoader().loadClass("com.example.MyClass");
```
<img alt="ClassLoader in Java" height="inherit" src="https://media.geeksforgeeks.org/wp-content/uploads/jvmclassloader.jpg" width="inherit">
### Delegation Model
JVM和ClassLoader使用了委托层次结构算法来加载classclassLoader运行原则如下
- classLoader永远会遵循委托层次结构原则
- 当jvm遇到class时其首先会检查该class是否已经被加载
- 如果该类未被加载那么jvm将会请求classloader sub-system去加载该类而classloader sub-system则会将该加载工作委托给Application ClassLoader
- Application Classloader会将该类的加载任务委托给Extension ClassLoader而Extension ClassLoader则是会再次将该加载任务委托给Bootstrap Classloader
- Bootstrap Classloader会在bootstrap classpathJDK/JRE/LIB/EXT路径下查找该类如果该class存在那么其将会被加载否则加载请求将会回到Extension Classloader
- Extension Classloader也会从Extension classpath下查找该类如果查找到该类则加载该类否则请求将会被委托给Application ClassLoader
- Application ClassLoader将会在Application classpath路径下查找该类如果类存在会加载该类否则其会抛出ClassNotFoundException
### Visibility Principle
可见性原则保证了`由parent classloader加载的类对于child classloader来说是可见的而child classloader加载的类对parent classloader来说是不可见的`
假设类`GEEK.class`被Extension ClassLoader加载那么该类仅被Extension ClassLoader和Application Classloader可见对于Bootstrap ClassLoader来说`GEEK.class`是不可见的。如果该类尝试通过Bootstrap ClassLoader再次加载其会报`ClassNotFoundException`
### Uniqueness Property
唯一性保证了class是唯一的其保证了由parent classloader加载的类不会再被child classloader加载。只有当parent classloader无法查找到该类时当前classloader才会尝试对其进行加载