Java中的类加载器是一个类本身,那么谁来加载类加载器类呢?

5

Java中的ClassLoader是一个类,用于加载Java中的类文件。

java.lang.ClassLoader是一个抽象类。

我的问题是这个java.lang.ClassLoader类是否与JVM的类加载器(1.引导类加载器 2.扩展类加载器 3.系统类加载器)有任何关系?

还是这个java.lang.ClassLoader是一个单独的类,可以用来创建自定义类加载器?

类加载器是Java运行时环境的一部分,它将Java类动态加载到Java虚拟机中。它负责定位库,读取其内容并加载库中包含的类。当JVM启动时,使用三个类加载器:

  1. 引导类加载器

  2. 扩展类加载器

  3. 系统类加载器

引导类加载器加载核心Java库。它是用本地代码编写的。引导类加载器负责将关键Java类(如java.lang.Object和其他运行时代码)加载到内存中。运行时类打包在jre/lib/rt.jar文件中。

扩展类加载器加载扩展目录中的代码。它由ExtClassLoader类实现。

系统类加载器加载在java.class.path上找到的代码,该路径映射到系统类路径变量。它由AppClassLoader类实现。默认情况下,所有用户类都由系统类加载器加载。

Java ClassLoader是分层的,每当提出加载类的请求时,它都将其委托给其父级,从而在运行时环境中保持唯一性。如果父类加载器找不到该类,则类加载器本身尝试加载该类。

这意味着首先System类加载器将请求委派给Extensions类加载器,后者将请求委派给Bootstrap类加载器,在此处搜索类,如果未找到,则Extensions类加载器将搜索类,如果未找到,则System类加载器将搜索类,如果未找到,则抛出ClassNotFoundException

JVM是否总是使用System类加载器来加载类?

请纠正我任何错误之处。

1个回答

5
“系统类加载器”这个术语是一个错误的称呼。正如你所正确指出的那样,它负责从类路径的位置加载应用程序类。
从Java 8开始,AppClassLoader和ExtClassLoader都是java.net.URLClassLoader的子类,后者是java.security.SecureClassLoader的子类,后者又是java.lang.ClassLoader的子类。所有这些类都由Bootstrap loader加载,解决了鸡生蛋问题。
每个运行时类都有一个定义类加载器。对于启动期间由Bootstrap loader定义的类,其定义类加载器是Bootstrap loader。当JVM初始化完成并尝试启动应用程序时,Application类加载器(又称为“系统类加载器”)将查询主类。Application类加载器将遵循标准的委托模型,首先查询其父级,Extension类加载器也是如此,任何创建类的类加载器都将是该类的定义类加载器。
现在,在解析另一个类引用的类或调用Class.forName(String)时,将使用包含引用的类的定义加载器来解析类。因此,当Application类加载器加载您的类myapp.foo.Bar并且它包含对javax.swing.JButton的引用时,将查询它的定义类加载器,即Application类加载器,遵循委托模型以最终得到由Bootstrap loader定义的javax.swing.JButton。因此,javax.swing.JButton中的类引用仅通过Bootstrap加载器解析,这意味着javax.swing.JButton不能包含对您的myapp.foo.Bar类的引用,因为它不在其范围内。
因此,JVM并不总是使用“系统类加载器”来加载类,而仅在解析由其(或子加载器)定义的类的类引用或在明确查询时,例如解析主类时才会使用“系统类加载器”。
有第三方类加载器不严格遵循父委派模型,但无论如何和向哪个加载器委派,每个类都会有一个定义加载器(由getClassLoader()返回),该加载器将用于解析类中的引用。JVM确保一个类中相同的符号名称始终解析为相同的运行时类,无论特定类加载器如何实现查找。
请注意,在Java 9中,Extension类加载器已被Platform类加载器所取代。这个类加载器可能偏离简单的父委派,也就是说,它可能会委派给Application类加载器来加载覆盖平台提供模块的应用程序提供的模块。此外,内置的类加载器不再是URLClassLoader的子类。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接