本教程是针对JDK 8编写的。本页中描述的示例和实践不利用后续版本中引入的改进,并可能使用不再可用的技术。
请参阅Java语言变更以获取Java SE 9及其后续版本中更新的语言特性的摘要。
请参阅JDK发行说明以获取所有JDK版本的新功能、增强功能以及已移除或已弃用选项的信息。
理解扩展类加载
扩展框架利用了类加载委托机制。当运行环境需要为应用程序加载一个新类时,它按照以下顺序在以下位置查找类:
- 引导类:运行时类在 rt.jar 中,国际化类在 i18n.jar 中,以及其他类。
- 已安装的扩展:JRE 的 lib/ext 目录中的 JAR 文件中的类,以及系统范围内的特定平台扩展目录(例如 Solaris™ 操作系统上的 /usr/jdk/packages/lib/ext,但请注意,该目录只适用于 Java™ 6 及更高版本)。
- 类路径:通过系统属性 java.class.path 指定的路径上的类,包括 JAR 文件中的类。如果类路径上的 JAR 文件具有带有
Class-Path
属性的清单文件,则还会搜索由 Class-Path
属性指定的 JAR 文件。默认情况下,java.class.path
属性的值为 .
,即当前目录。您可以使用 -classpath 或 -cp 命令行选项,或设置 CLASSPATH
环境变量来更改该值。命令行选项会覆盖 CLASSPATH
环境变量的设置。
上述优先级列表告诉您,例如,仅当在 rt.jar、i18n.jar 或已安装的扩展中找不到要加载的类时,才会搜索类路径。
除非您的软件为特殊目的实例化了自己的类加载器,否则您实际上不需要了解更多内容,只需记住这个优先级列表即可。特别是,您应该注意可能存在的类名冲突。例如,如果在类路径上列出了一个类,但运行时环境却加载了在已安装的扩展中找到的具有相同名称的另一个类,那么将会得到意外的结果。
Java类加载机制
Java平台使用委派模型来加载类。基本思想是每个类加载器都有一个“父”类加载器。在加载一个类时,类加载器首先将类的搜索委托给其父类加载器,然后再尝试找到类自身。
以下是类加载API的一些要点:
- java.lang.ClassLoader 及其子类中的构造方法允许您在实例化新类加载器时指定一个父类加载器。如果您没有显式指定父类加载器,则虚拟机的系统类加载器将被分配为默认父类加载器。
- ClassLoader 中的 loadClass 方法在调用时按顺序执行以下任务来加载类:
- 如果已经加载了类,则返回它。
- 否则,将类的搜索委托给父类加载器。
- 如果父类加载器找不到类,则 loadClass 调用 findClass 方法来查找并加载类。
- ClassLoader 的 findClass 方法在父类加载器未找到类时在当前类加载器中搜索类。当您在应用程序中实例化类加载器子类时,您可能想要重写此方法。
- java.net.URLClassLoader 类作为扩展和其他JAR文件的基本类加载器,覆盖了 java.lang.ClassLoader 的 findClass 方法,用于在一个或多个指定的URL中搜索类和资源。
要查看使用API与JAR文件相关的示例应用程序,请参阅本教程中的使用JAR相关API课程。
类加载和java命令
Java平台的类加载机制反映在java命令中。
- 在java工具中,-classpath选项是设置java.class.path属性的简写方式。
- -cp和-classpath选项是等效的。
- -jar选项用于运行打包在JAR文件中的应用程序。有关此选项的描述和示例,请参阅本教程中的运行JAR包装软件课程。