类加载器
类加载器
类加载器
什么是类加载器?
类加载器负责在加载阶段获取字节码文件并且加载到内存中,通过加载字节码数据放入内存转换成byte[],接下来调用虚拟机底层方法将byte[]转换成方法区和堆中的数据。
类加载器分为两大类,一类是Java代码中实现的(JDK提供的),一类是虚拟机底层源码实现的。
虚拟机底层实现的类加载器:
- 源码位于Java虚拟机的源码中,实现语言与虚拟机底层语言一致,如Hotspot使用C++语言;
- 主要加载程序运行时的基础类,保证Java程序中基础类被正确的加载,比如java.lang.String,确保其可靠性。
JDK中默认提供或自定义的加载器:
- JDK中默认提供了多种处理不同渠道的累加载器,我们也可以自己根据需求定制;
- 所有Java中实现的类加载器都需要继承ClassLoader这个抽象类;
类加载器有哪些?
启动类加载器(Bootstrap ClassLoader):
启动类加载器是最顶层的类加载器,负责加载 JDK 的核心类库(如 java.lang.、java.util. 等)。
它是由 C 或 C++ 编写的,用 JNI(Java Native Interface)接口实现,通常不继承 ClassLoader 类,而是 Object 类。
它加载 JAVA_HOME/lib 目录下的 rt.jar(核心类库),并且不能被 Java 程序访问。
扩展类加载器(Extension ClassLoader):
扩展类加载器负责加载 JDK 的扩展库(通常是 JAVA_HOME/lib/ext 目录下的 JAR 文件,或者 java.ext.dirs 环境变量指定的路径)。
它继承自 ClassLoader,并且其加载的类主要是 JDK 扩展的类,像 javax.* 等。
它位于启动类加载器和应用程序类加载器之间。
应用程序类加载器(Application ClassLoader):
应用程序类加载器又叫做系统类加载器,它负责加载用户类路径(CLASSPATH)下的类文件。
它加载 Java 应用程序中的类,通常从 -classpath 或 CLASSPATH 环境变量指定的路径中加载类。
它是最常见的类加载器,通常是通过 ClassLoader.getSystemClassLoader() 获取。
自定义类加载器
Java 允许开发者创建自定义类加载器,继承 ClassLoader 类并重写其中的 findClass() 方法来实现类的自定义加载。
自定义类加载器可以用于:
- 动态加载类。
- 加载特定路径下的类。
- 加载加密或压缩的类。
- 控制类的加载顺序等。
从 JDK 9 开始,Java 引入了 模块系统(Java Platform Module System,JPMS),并且对类加载器进行了重新设计。主要变化包括:
模块化类加载器: JDK 9 引入了新的类加载器,例如 ModuleClassLoader,用于支持模块系统。 平台类加载器(PlatformClassLoader): 新的平台类加载器替代了原来的扩展类加载器,它负责加载平台模块和 JDK 扩展的类。
什么是双亲委派机制?
双亲委派机制指的是: 自底向上查找是否加载过,再由顶向下进行加载
以应用类加载器来说,应用类加载器想要加载一个类,首先会检查自己是否已经加载该类,没有加载则向上级委派,扩展类加载器检查是否加载该类,也没有,向它的上级委派,启动类加载器检查是否加载该类,发现也没有,则自己尝试加载该类,如果此类不在自己的加载路径中,就交给下级加载,扩展类加载器也不能加载,最后应用类加载器加载该类。
它们之间的上下级关系并不是继承关系,而是每个java实现的类加载器中都保存了一个成员变量parent类加载器,
应用类加载器的parent是扩展类加载器,扩展类加载器的parent是null, 因为启动类加载器使用C++编写,也没有上级类加载器了。
作用:
- 保证类加载的安全性 通过双亲委派机制避免恶意代码替换JDK中的核心类库,比如java.lang.String,确保核心类库的完整性和安全性。
- 避免重复加载 双亲委派机制可以避免同一个类被多次加载。
Oracle 官方对类加载器的双亲委派机制有以下描述:
Class loaders use a delegation model to search for classes and resources. Each instance of a class loader has an associated parent class loader. When asked to find a class or resource, a class loader delegates the search to its parent before attempting to find the class or resource itself.
翻译: 类加载器使用委派模型来搜索类和资源。每个类加载器实例都有一个关联的父类加载器。当类加载器被要求寻找某个类或资源时,它会在尝试自行查找之前,将搜索任务委托给其父类加载器。