java委托_JAVA类加载的委托模型

关于JAVA的类加载器,网上有很多这方面资料,这里只做测试,不多累述。JVM有三个内置加载器:           bootstrapClassLoader(由C语言编写,固化在jvm上)、ExtClassLoader、AppClassLoader。三个加载器从上到下呈父子关系,形成了“类加载委托模型”:即儿子的事情,父亲能做的,他一定会代劳(以免累到儿子),父亲的事情,一定会自已做,即使自已无法完成,也不会劳及儿子。三个类的加载路径分别为(更多细节参考google):

BootstrapClassLoader:    sun.boot.class.pathExtClassLoader:     java.ext.dirs                                                                                  AppClassLoader:     java.class.path

首先定义两个类:

packageloader;

publicclassClassA {

publicstaticvoidmain(String args[]){

System.out.println("ClassA: "+ ClassA.class.getClassLoader());

ClassB a =newClassB();

System.out.println("ClassB: "+ ClassA.class.getClassLoader());

}

}

//

packageloader;

publicclassClassB {

}

拷贝三份到:C:\Java\jre6\classes(bootstrapClassLoader的搜索目录之一),C:\Java\jre6\lib\ext\classes(extClassLoader的搜索目录之一),F:\javawork\study\bin目录下,其中C:\Java\jre6为我JRE目录。一定不要搞错,因为你的机器可能会有很多JRE。

CMD到F:\javawork\study\bin目录

1. F:\javawork\study\bin>java loader.ClassA

ClassA: null

ClassB: null

两个都为空,这是因为当AppClassLoader(默认的系统类加载器)来加载CLASSA,首先委托其父ExtClassLoader去加载,然后AppClassLoader委托bootstrapClassLoader去加载,bootstrapClassLoader没有父加载器,只能自已完成,在自已加载目录C:\Java\jre6\classes下找到了CLASSA,加载成功。然后CLASSA的加载器bootstrapClassLoader加载CLASSB,同样在C:\Java\jre6\classes找到CLASSB,所以两个类的加载器都是bootstrapClassLoader,因为bootstrapClassLoader实现于C++,所以返回NULL。

2. 删除C:\Java\jre6\classes目录下的CLASSB

F:\javawork\study\bin>java loader.ClassA

ClassA: null

Exception in thread "main" java.lang.NoClassDefFoundError: loader/ClassB

at loader.ClassA.main(ClassA.java:6)

这是因为同(1)一样,最后由bootstrapClassLoader成功加载CLASSA,然后由CLASSA(这里叫CLASSB的CALLER)的加载器bootstrapClassLoader需要去加载CLASSB,但bootstrapClassLoader尽其力也没能找到(因为被我删了),这位慈爱的父亲到最后一刻都没有交给儿子ExtClassLoader去做,最后上报:我无能为力。

3.把(2)中删除的CLASSB还原,同时删创除该目录下的CLASSA

F:\javawork\study\bin>java loader.ClassA

ClassA: sun.misc.Launcher$ExtClassLoader@126b249

ClassB: null

两个都输出ExtClassLoader,顺着(1)的思路,AppClassLoader委托ExtClassLoader,ExtClassLoader委托bootstrapClassLoader,bootstrapClassLoader找不到CLASSA,只能放手让儿子去做(比如找女朋友这事,小伙子本来想老爸战友的女儿不错,可父亲去提亲,人家不应,“不行,儿子,你自个追其他的吧!”)。ExtClassLoader绝地逢生,在自已的区域内找到了CLASSA。然后CLASSA的加载器ExtClassLoader去加CLASSB, 同样道理这事交给老爸bootstrapClassLoader去做,bootstrapClassLoader责无旁贷,顺利完成,所以ClassB: null。

4.把(3)中剩下的CLASSB也删除。

同(1)一样,ExtClassLoader绝地逢生,在自已的区域内找到了CLASSA,然后CLASSA的加载器ExtClassLoader去加CLASSB,不幸的事,这次老爸bootstrapClassLoader却无能为力(被我CUT了)。最后ExtClassLoader自已搞定。

5.继序(4)删除C:\Java\jre6\lib\ext\classes目录下的CLASSB

F:\javawork\study\bin>java loader.ClassA

ClassA: sun.misc.Launcher$ExtClassLoader@126b249

Exception in thread "main" java.lang.NoClassDefFoundError: loader/ClassB

at loader.ClassA.main(ClassA.java:6)

按上面的思路,你一定知道为什么。

6.还原(5)中删除的CLASSB,同时删除CLASSA.

AppClassLoader(默认的系统类加载器)来加载CLASSA,首先委托其父ExtClassLoader去加载,然后AppClassLoader委托bootstrapClassLoader去加载.可两们前辈都无能为力,最后还是落到了AppClassLoader身上,少年英雄很快实现自已的梦想,成功加载CLASSA,然后其CLASSA的加载器(还是AppClassLoader)再去加载CLASSB,喜出望外的是,老爸ExtClassLoader代其完成,大功告成。

7.继序(6)删除C:\Java\jre6\lib\ext\classes目录下的CLASSB

同样道理,委托,委托。但这次AppClassLoader在我的破坏下(我删,删),只能自力更生。完成加载。

有一点问题,在测试过程中我的本机并没有CLASSPATH变量:

F:\javawork\study\bin>set classpath

环境变量 classpath 没有定义

但System.out.println(System.getProperty("java.class.path")) 输出:. 即当前目录作为了classpath.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值