java - 什么是 Java 类加载器?

标签 java classloader

简单说几句,什么是Java ClassLoader,什么时候用,为什么用?

好的,我读了一篇维基文章。 ClassLoader 加载类。行。因此,如果我包含 jar 文件并导入,则 ClassLoader 会完成这项工作。

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

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

最佳答案

取自这个不错的 tutorial来自太阳:

动机

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

当 Java 应用程序启动时,要运行的第一个类(或应用程序的入口点)是具有称为 main() 的 public static 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 允许您专注于业务逻辑而不是基 native 制的实现细节,从而简化您的生活。最近为了反射(reflect) Java 平台的成熟度而将 J2SE 1.5 更改为 J2SE 5.0 就证明了这一点。

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

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

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

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

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

关于java - 什么是 Java 类加载器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2424604/

相关文章:

Java类引用类的加载机制

java - 如何在 Java 中实现抽象单例类?

java - 类加载器 loadClass 抛出 ClassNotFoundException

java FileInputStream - 基于 File 对象引用方式的差异 : classloader/filesystem

java - 为什么 EAR 中的多个 ejb jar 共享相同的类加载器,而每个 WAR 都有自己的类加载器?

java - 如何使用 Hibernate 将 java.time.LocalDateTime 映射到 H2 数据库中的 TIMESTAMP?

java - 如何知道何时调用了 Parse.initialize()?

java - QSslSocket问题

java - (二维数组)Java错误: constant expression required

java - 自动分配编号变量名称