您的位置: 首页 > 软件教程 > Java教程专题 > Java类别载入器

Java类别载入器

8.1分
出处:网络 时间:2011-04-25

您可能感兴趣的话题: Java  

核心提示:Java的动态特性有两种,一是隐式的;另一种是显示的。

用如下示例测试:

public class AppLoader

{

public static void main(String[] args)

{

String s = System.getProperty("java.class.path");

System.out.println(s);

}

}

/////////////////////////////////////////////////////////////////

D:myappclassload>java AppLoader

.;D:myjavaTomcat5.0webappsaxisWEB-INFlibaxis.jar;D:myjavaTomcat5.0weba

ppsaxisWEB-INFlibcommons-logging.jar;D:myjavaTomcat5.0webappsaxisWEB-IN

Flibcommons-discovery.jar;C:oracleora81jdbclibclasses12.zip;D:myjavaJDB

CforSQLserverlibmssqlserver.jar;D:myjavaJDBCforSQLserverlibmsbase.jar;D:m

yjavaJDBCforSQLserverlibmsutil.jar;D:myjavaTomcat5.0commonlibservlet-api

.jar;D:myjavaj2sdk1.4.2_04jrelib t.jar;C:sunappserverlibj2ee.jar;D:myj

avaj2sdk1.4.2_04libjaxp.jar;D:myjavaj2sdk1.4.2_04libsax.jar;

D:myappclassload>java -classpath .;d:myapp AppLoader

.;d:myapp

/////////////////////////////////////////////////////////////////

从这个输出结果,我们可以看出,在预设情况下,AppClassLoader 的搜寻路径为”.”(目前所在目

录),如果使用-classpath 选项(与-cp 等效),就可以改变AppClassLoader 的搜寻路径,如果没有

指定-classpath 选项,就会搜寻环境变数CLASSPATH。如果同时有CLASSPATH 的环境设定与

-classpath 选项,则以-classpath 选项的内容为主,CLASSPATH 的环境设定与-classpath 选项两者

的内容不会有加成的效果。

至於ExtClassLoader 也有相同的情形,不过其搜寻路径是参考系统参数java.ext.dirs。

系统参数java.ext.dirs 的内容,会指向java.exe 所选择的JRE 所在位置下的libext 子目录。Java.exe使用的JRE是在系统变量path里指定的,可以通过修改path从而修改ExtCLassLoader的搜寻路径,也可以如下命令参数来更改,

java –Djava.ext.dirs=c:winnt AppLoader //注意 =号两边不能有空格。-D也不能和java分开。

////////////////////////////////////////////////////////////////

D:myappclassload>java ExtLoader

D:myjavaj2sdk1.4.2_04jrelibext

D:myappclassload>java -Djava.ext.dirs=c:winnt ExtLoader

c:winnt

////////////////////////////////////////////////////////////////

最後一个类别载入器是Bootstrap Loader , 我们可以经由查询由系统参数sun.boot.class.path 得知Bootstrap Loader 用来搜寻类别的路径。该路径的修改与ExtClassLoader的相同。但修改后不影响Bootstrap的搜寻路径。

在命令列下参数时,使用–classpath / -cp / 环境变数CLASSPATH 来更改AppClassLoader的搜寻路径,或者用–Djava.ext.dirs 来改变ExtClassLoader 的搜寻目录,两者都是有意义的。

可是用–Dsun.boot.class.path 来改变Bootstrap Loader 的搜寻路径是无效。这是因为

AppClassLoader 与ExtClassLoader 都是各自参考这两个系统参数的内容而建立,当您在命令列下

变更这两个系统参数之後, AppClassLoader 与ExtClassLoader 在建立实体的时候会参考这两个系

统参数,因而改变了它们搜寻类别档的路径;而系统参数sun.boot.class.path 则是预设与

Bootstrap Loader 的搜寻路径相同,就算您更改该系统参与,与Bootstrap Loader 完全无关。

改变java.exe所使用的jre会改变Bootstrap Loader的搜寻路径。

Bootstrap Loader的搜寻路径一般如下:

///////////////////////////////////////////////////////////////////////////////////

D:myjavaj2sdk1.4.2_04jrelib t.jar;D:myjavaj2sdk1.4.2_04jrelibi18n.jar;

D:myjavaj2sdk1.4.2_04jrelibsunrsasign.jar;D:myjavaj2sdk1.4.2_04jrelibj

sse.jar;D:myjavaj2sdk1.4.2_04jrelibjce.jar;D:myjavaj2sdk1.4.2_04jrelib

charsets.jar;D:myjavaj2sdk1.4.2_04jreclasses

///////////////////////////////////////////////////////////////////////////////////////

更重要的是,AppClassLoader 与ExtClassLoader 在整个虚拟机器之中只会存有一份,一旦建

立了,其内部所参考的搜寻路径将不再改变,也就是说,即使我们在程式里利用System.setProperty()

来改变系统参数的内容,仍然无法更动AppClassLoader 与ExtClassLoader 的搜寻路径。因此,执

行时期动态更改搜寻路径的设定是不可能的事情。如果因为特殊需求,有些类别的所在路径并非在

一开始时就能决定,那麽除了产生新的类别载入器来辅助我们载入所需的类别之外,没有其他方法了。

下面我们将看一下载入器的委派模型

所谓的委派模型,用简单的话来讲,就是「类别载入器有载入类别的需求时,会先请示其Parent 使用其搜寻路径帮忙载入,如果Parent 找不到,那麽才由自己依照自己的搜寻路径搜寻类别」。

下面我们看一下小的示例:

public class Test

{

public static void main(String[] args)

{

System.out.println(Test.class.getClassLoader());

TestLib tl = new TestLib();

tl.start();

}

}

public class TestLib

{

public void start()

{

System.out.println(this.getClass().getClassLoader());

}

}

  如果这两个类仅放在dos命令提示符的当前目录下,则输出结果如下:

//////////////////////////////////////////////////////

sun.misc.Launcher$AppClassLoader@1a0c10f

sun.misc.Launcher$AppClassLoader@1a0c10f

//////////////////////////////////////////////////////

如果这两个类同时又放在<JRE 所在目录>libextclasses 底下(在我的机器上是:D:myjavaj2sdk1.4.2_04jrelibextclasses,classes没有,需要自己建),输出结果如下:

/////////////////////////////////

sun.misc.Launcher$ExtClassLoader@e2eec8

sun.misc.Launcher$ExtClassLoader@e2eec8

////////////////////////////////////

最后如果在<JRE 所在目录>classes下放入这两个类,则输出结果为

/////////////////////////////////

null

null

////////////////////////////////////

如果把<JRE 所在目录>classes下的TestLib删去,则输出入下:

//////////////////////////////////////

null

Exception in thread "main" java.lang.NoClassDefFoundError: TestLib

at Test.main(Test.java:7)

//////////////////////////////////////

这是因为Test的classLoader是Bootstrap Loader ,因此TestLib的也默认为是Bootstrap Loader。Bootstrap Loader搜寻路径下的TestLib被删去了,Bootstrap Loader又没有parent,所以提示找不到。

其他的情况可以自己逐个添加或删除文件,然后执行java Test进行测试,察看输出结果。

AppClassLoader 与Bootstrap Loader会搜寻它们所指定的位置(或JAR 档),如果找不到就找不到了,AppClassLoader 与Bootstrap Loader不会递回式地搜寻这些位置下的其他路径或其他没有被指定的JAR 档。反观ExtClassLoader,所参考的系统参数是java.ext.dirs,意思是说,他会搜寻底下的所有JAR 档以及classes 目录,作为其搜寻路径。

网友评论
多特网友 2012-03-02 23:43:11 回复
都是英吉利是,怎么看得懂!擦
多特网友 2012-01-19 14:01:34 回复
没基础真的不能学习吗??看的我好晕哦!
多特网友 2012-01-19 14:01:34 回复
没基础真的不能学习吗??看的我好晕哦!
多特网友 2012-03-02 23:43:11 回复
都是英吉利是,怎么看得懂!擦
精品软件课程
更多 >
C++是一种静态数据类型检查的,支持多重编程... [详细]
C语言是一种面向过程的计算机程序设计语言。多... [详细]
Visual Basic是一种由微软公司开发... [详细]
Oracle Database,又名Orac... [详细]
Visual Basic.NET是从 Vis... [详细]
Visual C++微软公司的C++开发工具... [详细]