//查看被加载的TestBean类型是被那个类加载器加载的
System.out.println(typeLoaded.getClassLoader());
} catch (Exception e) {
e.printStackTrace();
}
}
}
对应的输出如下:
D:"DEMO"dev"Study"ClassLoaderTest"bin
sun.misc.Launcher$AppClassLoader@197d257
(说明:当前类路径默认的含有的一个条目就是工程的输出目录)
测试二:
将当前工程输出目录下的…/classloader/test/bean/TestBean.class打包进test.jar剪贴到< Java_Runtime_Home >/lib/ext目录下(现在工程输出目录下和JRE扩展目录下都有待加载类型的class文件)。再运行测试一测试代码,结果如下:
D:"DEMO"dev"Study"ClassLoaderTest"bin
sun.misc.Launcher$ExtClassLoader@7259da
对比测试一和测试二,我们明显可以验证前面说的双亲委派机制,系统类加载器在接到加载classloader.test.bean.TestBean类型的请求时,首先将请求委派给父类加载器(标准扩展类加载器),标准扩展类加载器抢先完成了加载请求。
测试三:
将test.jar拷贝一份到< Java_Runtime_Home >/lib下,运行测试代码,输出如下:
D:"DEMO"dev"Study"ClassLoaderTest"bin
sun.misc.Launcher$ExtClassLoader@7259da
测试三和测试二输出结果一致。那就是说,放置到< Java_Runtime_Home >/lib目录下的TestBean对应的class字节码并没有被加载,这其实和前面讲的双亲委派机制并不矛盾。虚拟机出于安全等因素考虑,不会加载< Java_Runtime_Home >/lib存在的陌生类,开发者通过将要加载的非JDK自身的类放置到此目录下期待启动类加载器加载是不可能的。做个进一步验证,删除< Java_Runtime_Home >/lib/ext目录下和工程输出目录下的TestBean对应的class文件,然后再运行测试代码,则将会有 ClassNotFoundException异常抛出。有关这个问题,大家可以在java.lang.ClassLoader中的 loadClass(String name, boolean resolve)方法中设置相应断点运行测试三进行调试,会发现findBootstrapClass0()会抛出异常,然后在下面的findClass 方法中被加载,当前运行的类加载器正是扩展类加载器(sun.misc.Launcher$ExtClassLoader),这一点可以通过JDT中变量视图查看验证。
(5)被不同的ClassLoader加载的两个类之间有什么限制和不同?
现在我们来看一下一个现象:
在eclipse里面我是这样做的:
OneCls.java
package org.corey.one;
import org.corey.two.TwoCls;
public class OneCls {
public OneCls() {
System.out.println();