# 了解扩展类加载

> 原文： [https://docs.oracle.com/javase/tutorial/ext/basics/load.html](https://docs.oracle.com/javase/tutorial/ext/basics/load.html)

扩展框架使用类加载委托机制。当运行时环境需要为应用程序加载新类时，它将按顺序在以下位置查找该类：

1.  **Bootstrap 类**： `rt.jar` 中的运行时类， `i18n.jar` 中的国际化类等。
2.  **已安装的扩展**：JRE 的 `lib / ext` 目录中的 JAR 文件中的类，以及系统范围内特定于平台的扩展目录（例如 `/ usr / Solaris™操作系统上的 jdk / packages / lib / ext` ，但请注意，此目录的使用仅适用于 Java™6 及更高版本。
3.  **类路径**：类，包括 JAR 文件中的类，由系统属性 `java.class.path` 指定的路径。如果类路径上的 JAR 文件具有带有`Class-Path`属性的清单，则还将搜索由`Class-Path`属性指定的 JAR 文件。默认情况下，`java.class.path`属性的值为`.`，即当前目录。您可以使用 `- 类路径`或 `-cp` 命令行选项或设置`CLASSPATH`环境变量来更改该值。命令行选项会覆盖`CLASSPATH`环境变量的设置。

例如，优先级列表告诉您，只有在 `rt.jar` ， `i18n.jar` 中的类中未找到要加载的类时才会搜索类路径。或已安装的扩展程序。

除非您的软件出于特殊目的而实例化其自己的类加载器，否则您实际上并不需要了解这一点，而是要记住这个优先级列表。特别是，您应该知道可能存在的任何类名冲突。例如，如果在类路径上列出一个类，如果运行时环境改为加载在已安装的扩展中找到的同名的另一个类，则会得到意外的结果。

## Java 类加载机制

Java 平台使用委托模型来加载类。基本思想是每个类加载器都有一个“父”类加载器。在加载类时，类加载器首先将对类的搜索“委托”到其父类加载器，然后再尝试查找类本身。

以下是类加载 API 的一些亮点：

*   `java.lang.ClassLoader` 及其子类中的构造函数允许您在实例化新的类加载器时指定父类。如果未明确指定父级，则将将虚拟机的系统类装入器指定为默认父级。
*   `ClassLoader` 中的 `loadClass` 方法在调用加载类时按顺序执行这些任务：
    1.  如果已经加载了一个类，则返回它。
    2.  否则，它将搜索新类委托给父类加载器。
    3.  如果父类加载器没有找到类， `loadClass` 调用方法 `findClass` 来查找并加载该类。
*   如果父类加载器找不到类， `ClassLoader` 的 `findClass` 方法将在当前类加载器中搜索该类。在应用程序中实例化类加载器子类时，您可能希望覆盖此方法。
*   `java.net.URLClassLoader` 类作为扩展和其他 JAR 文件的基本类加载器，覆盖 `java.lang.ClassLoader` 的 `findClass` 方法进行搜索类和资源的一个或多个指定的 URL。

要查看使用与 JAR 文件相关的某些 API 的示例应用程序，请参阅本教程中的[使用 JAR 相关 API](../../deployment/jar/apiindex.html) 课程。

## 类加载和 `java` 命令

Java 平台的类加载机制反映在 `java` 命令中。

*   在 `java` 工具中， `-classpath` 选项是设置 `java.class.path` 属性的简便方法。
*   `-cp` 和 `- 类路径`选项是等效的。
*   `-jar` 选项运行打包在 JAR 文件中的应用程序。有关此选项的说明和示例，请参阅本教程中的[正在运行的 JAR 包装软件](../../deployment/jar/run.html)课程。