主页传送门:📀 传送
概述
JVM(Java虚拟机)的类加载器是Java的核心组件之一,负责将Java字节码文件加载到JVM中,并将其转换为可以执行的Java类。
类加载器的主要职责:
- 加载类:根据类的全限定名,将类的字节码文件加载到JVM中,并为其创建一个Class对象。
- 链接类:验证类的字节码是否符合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类加载器有以下特点:
- 分层:JVM类加载器分为多个层次,每个层次都有自己的类加载器和父级类加载器。开发者可以创建自定义类加载器,并将其添加到任何级别的层次中。
- 隔离:每个类加载器都有自己的命名空间,其中包含由其加载的所有类。因此,不同类加载器可以加载具有相同名称的类,但这些类的实例不会相互干扰。
- 动态性:开发者可以创建自定义类加载器来动态地加载Java类。例如,Web服务器可以使用自定义类加载器来加载Web应用程序所需的Java类。
- 缓存:JVM会缓存已加载的类的元数据信息,以便在再次需要时快速访问。
类加载机制
动态类加载
类名称空间
判断类是否“相等”?
任意一个类,都由加载它的类加载器和这个类本身一同确立其在 Java 虚拟机中的唯一性,每一个类加载器,都有一个独立的类名称空间。
因此,比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个 Class 文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那么这两个类就必定不相等。
这里的“相等”,包括代表类的 Class 对象的 equals() 方法、isInstance() 方法的返回结果,也包括使用 instanceof 关键字做对象所属关系判定等情况。
性能优化
- 减少类加载器的数量:在应用程序中使用过多的类加载器会降低性能,因此应该尽量减少类加载器的数量。
- 使用缓存:对于已经加载的类,可以使用缓存技术进行存储和管理,避免重复加载同一个类。Java中的类加载器可以缓存已经加载的类,因此使用缓存可以减少加载时间和提高性能。
- 使用类预加载技术:对于需要经常使用的类,可以使用类预加载技术,通过预先加载类来提高类的访问速度。可以使用静态变量或者单例模式等技术来预加载类。
- 优化类的加载顺序:对于应用程序中频繁使用的类,可以优化它们的加载顺序,使其先加载,从而减少应用程序的启动时间。
- 使用轻量级类库:Java中有许多轻量级的类库,可以提高应用程序的性能。这些类库通常具有更小的代码库和更快的加载速度,因此可以提高应用程序的性能。
- 使用JIT优化:Java HotSpot虚拟机中自带JIT编译器,可以将字节码编译为本地机器码,从而提高性能。
参考文献
虚拟机规范
深入理解Java虚拟机
openjdk文章来源:https://www.toymoban.com/news/detail-715139.html
文章来源地址https://www.toymoban.com/news/detail-715139.html
如果喜欢的话,欢迎 🤞关注 👍点赞 💬评论 🤝收藏 🙌一起讨论 你的支持就是我✍️创作的动力! 💞💞💞
到了这里,关于JVM类加载器大比拼:谁才是Java程序的真正主宰?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!