Extension classes。这些类扩展了 Java 平台,或者说,这些类利用了 Java 的扩展机制。这些类有两个要求:其一是必须打包成 jar,不能是单独的 .class 文件,并且这些 jar 包必须存放于 JDK/jre/lib/ext 目录下;其二是这些类不能引用 Bootstrap classes 和 Extension classes 之外的类。
User classes。也就是用户自定义类。我们自己写的程序已经我们从其它地方下载的第三方库都属于这个范畴。JVM 最后加载这些类,到哪里去找呢?这就需要用到 CLASSPATH 环境变量了,或者在程序启动的时候使用 -classpath 参数。
在以上三个过程中,用户其实并不需要指定 Bootstrap classes 和 Extension classes 所在的目录,只需要指定 User classes 所在的目录就可以了。这是 JDK 8 和之前版本的区别。Bootstrap classes 和 Extension classes 所在的路径可以自动搜寻。前面的图片中我标出的 Java 系统配置中的 sun.boot.class.path 项就代表了 Bootstrap classes 所在的目录,默认为 JDK/jre/lib 中的 rt.jar 和其它一些 jar 文件。可以在启动程序的时候使用 -Xbootclasspath 选项更改这个路径。而 Extension classes 的路径就是 JDK/jre/lib/ext 目录,在前面的图片中我也标出来了。
关于 User classes 的搜索路径,如果不指定的话,默认就是当前目录.,我前面图片中标出的就是默认值。如果重新指定 User classes 的搜索路径的话,就不会从当前目录进行搜索了,如果要从当前目录进行搜索,必须将当前目录明确地添加到 CLASSPATH 中。指定 User classes 的搜索路径有以下几种方式:
设置 CLASSPATH 环境变量;
程序启动时使用 -cp 或 -classpath 选项;
如果使用 java -jar 方式启动程序,则从 jar 包中的 manifest 文件中的 Class-Path 配置项中指定的路径搜索。
搜索路径可以是目录,也可以是 jar 包,也可以是它们之间的任意组合,每一个项之间用:分割。另外,路径中还可以使用通配符*,但是该通配符只能匹配某一个目录下的所有 jar 包,而不能匹配 .class 文件,更加不能匹配子目录。
那么问题来了,既然 CLASSPATH 中可以包含 jar 包,而 jar 包中又可以指定 Class-Path,而这个 Class-Path 中又可以指定其它的 jar 包,这样会造成无限循环吗?JVM 在搜索 jar 包的时候有什么规则吗?有的,如下三条:
jar包中指定的 Class-Path 会被当成 CLASSPATH 的组成部分,并且放在 jar 包中的其它 class 文件之前,而 class 文件的搜索是按照其路径出现在 CLASSPATH 中的顺序进行的,先找到先得。
如果之前扫面过的 jar 包又出现了,就不进行重复扫描;
如果一个 jar 包是作为 Java 的扩展安装的,也就是其在 JDK/jre/lib/ext 目录中,就忽略它的 Class-Path 配置项。
关于 javac、javadoc 命令和 tools.jar 又有一些例外,这些例外的存在是因为 javac、javadoc 这些程序的运行对 .class 文件的双重需求决定的。作为 JDK 的工具, javac、javadoc 的运行需要 tools.jar 中的类的支持,另外,当 javac、javadoc 编译程序的时候,又需要解析源代码中对其它类的引用。它的基本规则如下:
运行 javac、javadoc 这些命令时,这些命令本身使用的 Bootstrap classes 、Extension classes 和 tools.jar 是不能改变的,它们只使用它们所在的 JDK 中的版本;
如果是 javac、javadoc 需要解析的其它的代码中用到了 tools.jar 中的类,则必须将 tools.jar 加入到 User classes 的搜索路径中才能起作用;如果要让它们解析的代码中引用不同版本的 Bootstrap classes 和 Extension classes,可以使用这两个命令的 -bootclasspath 和 -extdirs 选项指定。