主页传送门: 传送
JVM(Java虚拟机)的类加载器是Java的核心组件之一,负责将Java字节码文件加载到JVM中,并将其转换为可以执行的Java类。
类加载器的主要职责:
类加载器是Java虚拟机(JVM)中的一个组件,它的主要作用是将Java源代码编译成可执行的字节码,并将其加载到JVM中。
类加载器在Java中扮演着关键的角色,它们使Java具备了动态加载和隔离不同类的能力。具体来说,类加载器负责从文件系统、网络或其他来源读取类文件(.class文件),并将其转换为JVM中的可执行代码。这个过程分为两个步骤:首先是加载类,通过读取类文件并创建一个代表该类的Class对象;其次是链接类,包括验证、准备和解析类文件中的符号引用。
类加载器还遵循双亲委派模型,即子类加载器在收到类加载请求时,首先将请求委派给父类加载器,只有在父类加载器无法完成加载请求时,子类加载器才会尝试自己去加载。这种机制可以保证Java核心API的稳定性和防止某些安全问题。
类加载器主要有三种:启动类加载器、扩展类加载器和系统类加载器。启动类加载器负责加载Java核心类库,扩展类加载器负责加载java.ext.dirs系统属性中指定的目录或JDK安装目录的lib/ext子目录下的类库,而系统类加载器则负责从Classpath环境变量中加载应用相关的类。
Bootstrap ClassLoader
(启动类加载器)是Java虚拟机(JVM)中的一种特殊类加载器,它是JVM的内部组成部分,主要负责加载Java核心类库,如java.lang
包中的类以及其他基础的类,这些类通常是JVM运行所必需的类。
Bootstrap ClassLoader
的主要特点:
加载核心类库: Bootstrap ClassLoader
负责加载JVM运行时环境所需的核心类库,这些类库通常包括Java标准库中的一些基础类,如Object类、String类等。这些类在JVM启动时就会被加载,因此无法通过普通的类加载器重新加载或替换。
不是普通的ClassLoader: Bootstrap ClassLoader
不是普通的Java类加载器,它通常是用本地代码(C/C++)实现的,与普通的Java类加载器不同。这使得它能够加载基础类库,而不受Java应用程序的类加载器体系的影响。
无法被替换: 由于Bootstrap ClassLoader
加载的类是JVM运行所必需的核心类库,它们不能被普通的Java类加载器替换或重新加载。这确保了JVM的稳定性和安全性。
Bootstrap ClassLoader
是JVM的内部组件,负责加载JVM运行所需的核心类库,具有特殊的地位和特点,通常不会被普通的Java应用程序代码所涉及。
示例:
public class Main {
public static void main(String[] args) {
// 使用核心类
String message = "Hello, World!";
System.out.println(message);
// 使用Object类
Object obj = new Object();
// 等等...
}
}
Extension ClassLoader
(扩展类加载器)是Java虚拟机(JVM)的一个重要组成部分,它的主要职责是加载Java标准扩展库中的类和用户自定义的扩展类。
Extension ClassLoader
的主要职责和工作方式:
加载扩展类库: Extension ClassLoader
负责加载位于JRE(Java Runtime Environment)的lib/ext
目录下的JAR文件中的类。这些JAR文件包含了Java标准扩展库,例如Java Cryptography Extension(JCE)或Java Naming and Directory Interface(JNDI)等。
工作方式: Extension ClassLoader
是JVM中的一个普通的Java类加载器,它的工作方式与其他普通的类加载器类似,但有一点不同,它是通过父类加载器的方式工作的。通常情况下,Extension ClassLoader
的父类加载器是Bootstrap ClassLoader
。这意味着它首先会尝试从Bootstrap ClassLoader
加载类,如果找不到类,它才会尝试从自己的类路径中加载。
类路径: Extension ClassLoader
的类路径通常包括JRE的lib/ext
目录下的JAR文件。这个类路径是通过系统属性 java.ext.dirs
来指定的。
用户自定义扩展类: 除了加载标准扩展库,Extension ClassLoader还可以加载用户自定义的扩展类,只要这些类位于java.ext.dirs
目录下或其子目录中。这允许开发人员将自己的扩展类添加到JRE,以扩展Java的功能。
Extension ClassLoader
的主要职责是加载Java标准扩展库中的类和用户自定义的扩展类,它通过委派给Bootstrap ClassLoader
来加载标准扩展库中的类,同时也可以加载用户自定义的扩展类。这有助于扩展Java的功能和功能。
示例:
public class Main {
public static void main(String[] args) {
// 使用Extension ClassLoader加载自定义扩展类
MyExtensionClass extensionClass = new MyExtensionClass();
extensionClass.printMessage();
}
}
Application ClassLoader
(应用程序类加载器),也被称为System ClassLoader
,是Java虚拟机(JVM)中的一种类加载器。它的主要作用是加载应用程序开发者编写的Java类,这些类通常位于应用程序的类路径(Classpath)下。
Application ClassLoader
在应用程序中的作用:
加载应用程序类: Application ClassLoader
负责加载应用程序开发者编写的Java类,包括应用程序的主类和所有相关的库和依赖。这些类通常位于应用程序的类路径中,可以通过CLASSPATH环境变量或者 -classpath
命令行参数来指定。
应用程序隔离性: Application ClassLoader
为不同的Java应用程序提供了隔离性。不同的Java应用程序可以拥有自己独立的类加载器实例,这样它们不会相互干扰,即使它们使用相同的类名也不会发生冲突。这有助于确保应用程序的独立性和隔离性。
动态加载: Application ClassLoader
允许应用程序在运行时动态加载类。这对于插件化架构和动态模块加载非常有用,应用程序可以根据需要加载额外的类,而无需重新启动。
类版本控制: Application ClassLoader
还负责管理和控制已加载类的版本。如果应用程序需要升级某个类,它可以确保加载新版本的类而不会与旧版本发生冲突。
Application ClassLoader
在应用程序中的主要作用是加载应用程序开发者编写的Java类,提供应用程序隔离性,支持动态加载,并管理类的版本控制。这是Java应用程序在JVM中正常运行的关键组成部分。
示例:
public class Main {
public static void main(String[] args) {
/*
使用Application ClassLoader加载类
Application ClassLoader会自动加载应用程序类
*/
MyClass myObject = new MyClass();
myObject.printMessage();
}
}
class MyClass {
public void printMessage() {
System.out.println("Hello from MyClass!");
}
}
除了上述三种类加载器,还有一种比较特殊的类加载器——自定义类加载器(Custom Class Loader
)。自定义类加载器允许开发者自己实现类加载器的逻辑,以满足特定场景的需求。这些类加载器需要继承自ClassLoader
类,并重写findClass()
方法来指定加载过程。例如,可以实现一个加载指定路径下所有jar文件的类加载器,或者实现一个加密/解密字节码的类加载器等。想了解更多自定义类加载器的可以看上文动态类加载
在Java中,类加载器的继承关系为:ClassLoader
->SecureClassLoader
-> URLClassLoader
-> AppClassLoader
-> ExtClassLoader
-> BootstrapClassLoader
。其中,AppClassLoader
和ExtClassLoader
是系统类加载器和扩展类加载器的实例,而BootstrapClassLoader
是启动类加载器的实例。开发者可以通过继承ClassLoader
类或URLClassLoader
类来实现自定义类加载器。
图解如下:
需要注意的是,Java虚拟机规范并没有强制要求实现这三种类型的类加载器,但是大多数Java虚拟机实现都会提供这三种类型的类加载器。
JVM类加载器有以下特点:
动态类加载
判断类是否“相等”?
任意一个类,都由加载它的类加载器和这个类本身一同确立其在 Java 虚拟机中的唯一性,每一个类加载器,都有一个独立的类名称空间。
因此,比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个 Class 文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那么这两个类就必定不相等。
这里的“相等”,包括代表类的 Class 对象的 equals() 方法、isInstance() 方法的返回结果,也包括使用 instanceof 关键字做对象所属关系判定等情况。
参考文献
虚拟机规范
深入理解Java虚拟机
openjdk
如果喜欢的话,欢迎 关注 点赞 评论 收藏 一起讨论 你的支持就是我✍️创作的动力!