小编典典

什么是 Java 类加载器?

all

简单的几句话,什么是 Java ClassLoader,什么时候使用,为什么使用?

好的,我读了一篇 wiki 文章。ClassLoader 加载类。好的。因此,如果我包含 jar 文件并导入,ClassLoader 就可以完成这项工作。

我为什么要打扰这个 ClassLoader?我从未使用过它,也不知道它的存在。

问题是,为什么 ClassLoader 类存在?还有,你如何在实践中使用它?(有案例,我知道。)


阅读 127

收藏
2022-08-05

共1个答案

小编典典

摘自Sun的这个不错的教程:

动机

用静态编译的编程语言(例如 C 和 C++)编写的应用程序被编译成本地的、特定于机器的指令并保存为可执行文件。将代码组合成可执行本机代码的过程称为链接 -
将单独编译的代码与共享库代码合并以创建可执行应用程序。这在动态编译的编程语言(例如 Java)中是不同的。在 Java 中,Java 编译器生成的
.class 文件保持原样,直到加载到 Java 虚拟机 (JVM) 中——换句话说,链接过程由 JVM 在运行时执行。类在“需要”的基础上加载到 JVM
中。当一个加载的类依赖于另一个类时,该类也会被加载。

启动 Java 应用程序时,要运行的第一个类(或应用程序的入口点)是具有称为 main() 的公共静态 void
方法的类。这个类通常有对其他类的引用,所有加载被引用类的尝试都是由类加载器来执行的。

要大致了解这种递归类加载以及类加载思想,请考虑以下简单类:

public class HelloApp {
   public static void main(String argv[]) {
      System.out.println("Aloha! Hello and Bye");
   }
}

如果您指定 -verbose:class
命令行选项运行此类,以便打印正在加载的类,您将获得如下所示的输出。请注意,这只是部分输出,因为列表太长,无法在此处显示。

prmpt>java -verbose:class HelloApp



[Opened C:\Program Files\Java\jre1.5.0\lib\rt.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jsse.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jce.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\charsets.jar]
[Loaded java.lang.Object from shared objects file]
[Loaded java.io.Serializable from shared objects file]
[Loaded java.lang.Comparable from shared objects file]
[Loaded java.lang.CharSequence from shared objects file]
[Loaded java.lang.String from shared objects file]
[Loaded java.lang.reflect.GenericDeclaration from shared objects file]
[Loaded java.lang.reflect.Type from shared objects file]
[Loaded java.lang.reflect.AnnotatedElement from shared objects file]
[Loaded java.lang.Class from shared objects file]
[Loaded java.lang.Cloneable from shared objects file]
[Loaded java.lang.ClassLoader from shared objects file]
[Loaded java.lang.System from shared objects file]
[Loaded java.lang.Throwable from shared objects file]
.
.
.
[Loaded java.security.BasicPermissionCollection from shared objects file]
[Loaded java.security.Principal from shared objects file]
[Loaded java.security.cert.Certificate from shared objects file]
[Loaded HelloApp from file:/C:/classes/]
Aloha! Hello and Bye
[Loaded java.lang.Shutdown from shared objects file]
[Loaded java.lang.Shutdown$Lock from shared objects file]

如您所见,应用程序类(HelloApp)所需的Java运行时类首先被加载。

Java 2 平台中的类加载器

Java 编程语言不断发展,以使应用程序开发人员的生活变得更加轻松。这是通过提供 API 来完成的,这些 API
允许您专注于业务逻辑而不是基本机制的实现细节,从而简化您的生活。最近为了反映 Java 平台的成熟度而将 J2SE 1.5 更改为 J2SE 5.0
可以证明这一点。

从 JDK 1.2 开始,JVM 中内置的引导类加载器负责加载 Java
运行时的类。此类加载器仅加载在引导类路径中找到的类,并且由于这些是受信任的类,因此不会像对不受信任的类执行验证过程。除了引导类加载器之外,JVM
还有一个扩展类加载器负责从标准扩展 API 加载类,还有一个系统类加载器从通用类路径和应用程序类加载类。

由于有不止一个类加载器,它们以一棵树的形式表示,其根是引导类加载器。每个类加载器都有一个对其父类加载器的引用。当要求类加载器加载一个类时,它会在尝试加载项目本身之前咨询其父类加载器。父级依次咨询其父级,依此类推。所以只有在所有祖先类加载器都找不到当前类加载器所涉及的类之后。换言之,使用了委托模型。

java.lang.ClassLoader 类

java.lang.ClassLoader一个抽象类,可以由需要扩展 JVM
动态加载类的方式的应用程序子类化。java.lang.ClassLoader(及其子类)中的构造函数允许您在实例化新的类加载器时指定父级。如果您没有明确指定父级,则虚拟机的系统类加载器将被指定为默认父级。换句话说,ClassLoader
类使用委托模型来搜索类和资源。因此,ClassLoader
的每个实例都有一个关联的父类加载器,因此当请求查找类或资源时,在尝试查找类或资源本身之前,将任务委托给其父类加载器。loadClass()ClassLoader的方法在调用加载类时按顺序执行以下任务:

如果一个类已经被加载,它会返回它。否则,它将对新类的搜索委托给父类加载器。如果父类加载器没有找到该类,loadClass()则调用该方法findClass()查找并加载该类。finalClass()如果父类加载器未找到该类,则该方法在当前类加载器中搜索该类。


原始文章中还有更多内容,它还向您展示了如何实现自己的网络类加载器,它回答了您关于为什么(以及如何)的问题。另请参阅API
文档

2022-08-05