• How the Java Launcher Finds Classes
  • How the Java Launcher Finds Bootstrap Classes
  • How the Java Launcher Finds Extension Classes
  • How the Java Launcher Finds User Classes
  • How the Java Launcher Finds JAR-class-path Classes
  • How javac and javadoc Find Classes
  • Class Loading and Security Policies

(翻译自 How Classes are Found)

#Java启动器怎样查找类?# Java启动器(在windows中即java.exe)首先初始化Java虚拟机实例,在JVM中按以下顺序查找和加载类:

  • 引导类——组成Java平台的类,包括rt.jar和其他一些重要的jar文件中的类。
  • 扩展类——使用Java扩展机制的类,被打包在扩展目录(%JAVA_HOME%\jre\lib\ext)中的.jar文件中。
  • 用户类——用户和第三方开发者利用扩展机制定义的类,可在命令行工具上使用-classpath选项,或设定CLASSPATH环境变量,指定这些类所处位置。

实际上,这三种查找路径结合在一起就组成了一个简单的类查找路径,这与以前使用的单调的类查找路径相似,但当前的类查找机制有一些重要的区别:

  • 很难去隐藏或省略引导类
  • 你只需指明用户类的位置,引导类和扩展类可自动找到。
  • 工具类如今存放在独立的包(tools.jar)中,只有被包含在用户类路径中才能使用。

##Java启动器怎样查找引导类?##

引导类是实现Java2平台的类,包含在rt.jar和jre/lib中其他一些包中。这些包是由sun.boot.class.path系统属性值所指定的,这个系统属性只能引用,不能直接修改。

一般你不太可能重新定义引导类的路径,但当需要使用一组不同的核心类时,你可以使用非标准选项-Xbootclasspath重新指定此路径。

注意实现Java 2 SDK tools的类存放在一个与引导类不同的包文件(jdk@VERSION/lib/tools.jar)。开发工具调用java启动器时将此包加到用户类路径中,但处理源代码的编译器javac和文档生成工具javadoc仍使用原来不包含tools.jar的用户类路径(更多看下面javac和javadoc怎样查找类?)。

##Java启动器怎样查找扩展类?##

扩展类是指扩展Java平台的类,在扩展目录(jre/lib/ext)中的每个.jar文件都是一个扩展,通过使用Java Extension Framework加载这些类。在这个目录中不存在松散的类文件,而必须是被压缩在.jar文件或.zip文件中。安装之后,扩展类目录的位置不能更改

如果jre/lib/ext目录中包含多个.jar文件,并且这些文件中包含相同名字的类,比如

smart-extension1_0.jar 中包含类 smart.extension.Smart
smart-extension1_1.jar 中包含类 smart.extension.Smart

那么实际加载的类将是不明确的。

##Java启动器怎样查找用户类?## 用户类是构建在Java平台之上的类,Java启动器在用户类路径中查找用户类。用户类路径(user class path)——包含class文件的目录或jar文件或zip文件。

每个class文件有个子路径名,这个名字反映了这个类的完整路径名。例如,如果类com.mypackage.MyClass 存放在/myclasses目录中,那么目录/myclasses必须包含在用户类路径中,这个class文件的完整路径为/myclasses/com/mypackage/MyClass.class。如果这个类存放在一个名为myclasses.jar的包文件中,那么myclasses.jar文件必须包含在用户类路径中,这个class文件在压缩文件中以com/mypackage/MyClass.class的路径存在。

用户类路径是个字符串,在Solaris中各项被冒号“:”隔开,在Windows中各项被分号“;”隔开。java启动器将用户类路径存放在java.class.path系统属性中,这个属性值的可能来源有:

  • 默认值".",指的是用户类在当前目录(or under it,if in a package)下的所有class文件。
  • CLASSPATH环境变量值,它将覆盖掉默认值。
  • 命令行上的-cp或-classpath选项指定的值,它将覆盖掉默认值和CLASSPATH环境变量值。
  • -jar选项指定的JAR包文件,它将覆盖掉上面三个值,如果这个选项指定了,那么所有用户类都必须在这个指定的包文件中。

##Java启动器怎样查找JAR-class-path类?##

JAR文件中通常包含一个清单文件(manifest),其中列出JAR的内容。这个清单文件定义了一个JAR-class-path,这个路径扩展了类查找路径(只限于执行这个JAR加载类时)。通过JAR-class-path查找类的顺序为:

  • 通常,查找类时每个JAR-class-path条目所引用的类就像是JAR文件中的一部分,JAR-class-path中的各项按前后顺序扫描查找。
  • 如果JAR-class-path指向的JAR文件已经扫描过,那么以后就不必再扫描。(例如一个扩展或JAR文件在类路径中先前出现过,这项优化提高了效率,避免了循环查找。)
  • 如果JAR文件被当做一个扩展被安装,那么它定义的任何JAR-class-path都将被忽略。扩展所使用的类被假定为SDK的一部分或是已经安装为扩展。

#javac和javadoc怎样查找类?#

javac和javadoc工具以两种不同的方式使用类文件:

  • 像其他任何java程序一样,javac和javadoc运行时必须按顺序加载各种各样的类。
  • 为处理源代码,javac和javadoc还必须获取源代码中使用对象的类型信息。

解析源代码引用所使用的类文件与运行javac、javadoc所使用的类文件大多是相同的,但也有些例外:

  • javac和javadoc解析引用的类和接口经常与javac和javadoc工具的实现无关。解析的用户类和接口信息以class文件或源代码文件或两者都有的方式存在。
  • tools.jar文件中的工具类只有在运行javac和javadoc时才会被调用,工具类只有在tools.jar被包含在用户类路径中时才能被使用。
  • 程序员可能想使用另一个Java平台实现来解析引导类和扩展类引用,javac和javadoc使用选项-bootclasspath和-extdirs支持这项操作,但使用这项选项,javac和javadoc运行自身所加载的类文件不会改变。

如果一个引用的类在class文件和源文件中都有定义,那么javadoc总是使用源文件(javadoc不编译源文件),而javac总是使用class文件,并自动重编译过期的class文件。自动重编译的规则可参见javac文档(WindowsSolaris)。

默认情况下,查找class文件和源文件,javac和javadoc都扫描用户类路径。如果-sourcepath选项被指定,javac和javadoc只在指定的源文件路径中查找源文件,在用户类路径中查找class文件。

#类加载和安全策略#

类和接口必须被类加载器加载后才能使用,所使用的类加载器的类别决定使用怎样的安全策略。

程序可以通过调用类加载器实例的loadClass方法加载类和接口,但是通常情况下只需简单引用就可以加载相应类和接口,这是因为内置的类加载器在起作用,它会对扩展类和用户类施行相应安全策略。如果安全策略不可用,那么所有类都被是可信的(trusted),即便安全策略可用,也对启动类无效,启动类总是可信的(trusted)。

安全策略可用时,是由系统和用户策略文件配置的。Java 2 SDK中包含一份系统策略文件,将可信(trusted)状态授予扩展类,而对用户类给予基本限制。

使用或配置安全策略,可参见安全特点

注意:Java1.1平台上的一些安全编程技巧与Java 2平台类加载模型不兼容。