Java学习之java命令如何查找Classes – skyWalker

使用Java很多年了,虽然对如何搜索classes有一定的认识,但精通却不敢妄说。尤其是最近在使用getResourceAsStream加载属性文件时,遇到了不大不小的几个问题,当然遇到的问题与不熟悉Class.getResourceAsStream和ClassLoader. getResourceAsStream有直接关系,但多少与没有彻底理解Java中搜索classes的原理有关,所以在总结Class.getResourceAsStream和ClassLoader. getResourceAsStream的用法和区别之前,先学习一下Java是如何搜索classes的。

在Java中存在三种类型的class,分别是:启动程序classes(Bootstrapclasses)、扩展classes(Extension classes)和用户自定义类(即程序员实现的各种类)。启动程序classes组成了Java平台,包括rt.jar和其它jar包中的类。扩展classes使用了Java的扩展机制,位于jre/lib/ext目录中。用户classes由开发人员实现,在命令行使用-classpath选项或者设置CLASSPATH环境变量标识用户classes的位置。

当在命令行使用java命令执行class文件时,该命令启动Java虚拟机,虚拟机按照启动程序classes、扩展classes和用户classes的顺序搜索和加载类,这三种路径组成了类路径。在现如今的版本中,启动程序classes和扩展classes会被Java虚拟机自动发现和加载,只需要指定用户classes的位置,即使用-classpath或者设置CLASSPATH环境变量,工具类位于tools.jar中,要想使用工具类必须在classpath中包含tools.jar。

查找启动程序classes

可以System.getProperty("sun.boot.class.path")方法查看包含classes的jar文件,在本机上该方法的输出如下:

D:\software\Java\jre6\lib\resources.jar;D:\software\Java\jre6\lib\rt.jar;D:\software\Java\jre6\lib\sunrsasign.jar;D:\software\Java\jre6\lib\jsse.jar;D:\software\Java\jre6\lib\jce.jar;D:\software\Java\jre6\lib\charsets.jar;D:\software\Java\jre6\lib\modules\jdk.boot.jar;D:\software\Java\jre6\classes

几乎不会出现需要重新定义启动程序类路径的情况,不过还是提供了非标准选项–Xbootclasspath允许设置不同的启动程序类路径。

查找扩展classes

扩展classes扩展了Java平台,位于jre/lib/ext目录中。需要注意的是扩展classes必须被打包为jar或者zip文件,否则不会被查找到。不像启动程序classes,没有选项用于更改扩展classes的目录。如果jre/lib/ext目录包含多个jar文件,并且这些jar文件包含相同名称的类,如:

smart-extension1_0.jar contains class smart.extension.Smartsmart-extension1_1.jar contains class smart.extension.Smart

那么实际被加载的类是未定义的。

查找用户classes

用户classes是建立在Java平台基础上的类,为了查找用户classes,Java启动器引用用户的classpath,即包含类文件的目录、jar文件和zip文件的列表。类文件有一个反射类全限定名称的子路径名称,例如如果类com.mypackage.MyClass保存在/myclasses,那么/myclasses必须在用户类路径中,类文件的完整路径为/myclasses/com/mypackage/MyClass.class。如果类文件保存在名为myClasses.jar的jar文件中,那么该jar文件必须位于类路径中,并且类文件必须以com/mypackage/MyClass.class保存在jar文件中。

用户的类路径为一个字符串,在Linux系统中使用冒号(:)分隔不同的项,在Windows上使用分号(;)分隔不同的项。Java启动器将类路径字符串放入java.class.path系统属性中,可以使用System.getProperty("java.class.path")查看该属性的值。该属性的可能的值为:

默认值.,意味着用户类文件为当前目录下的所有类文件或者该目录下包中的类文件。 CLASSPATH环境变量的值,该值将会覆盖默认值。 -cp或者-classpath命令行选项指定的值,该值将覆盖默认值和CLASSPATH的值。 -jar选项执行的jar文件,该值将覆盖掉所有其它的值,即默认值,CLASSPATH的值和-cp或-classpath指定的值。如果使用了-jar选项,所有的用户类文件必须为jar文件中的类文件。

对于最后一条规则,可以通过实际情况验证一下,在bin目录包含属性文件test.properties。将测试代码打包为test-classpath.jar,然后在命令行运行java –jartest-classpath.jar,结果如下:

D:\BigData\TestClassPath\bin>java -jar test-classpath.jarClass.getResourceAsStream can not find resource on classpathClassLoader.getResourceAsStreamcan not find resource on classpath

而直接运行java test.TestGetResourceAsStream的结果如下:

D:\BigData\TestClassPath\bin>java test.TestGetResourceAsStream

Class.getResourceAsStream can not find resource on classpathClassLoader.getResourceAsStream:Hello world!

由结果验证了当使用-jar选项时,将会覆盖所有其它的值。你在会议中吵架时,尼泊尔的背包客一起端起酒杯坐在火堆旁。

Java学习之java命令如何查找Classes – skyWalker

相关文章:

你感兴趣的文章:

标签云: