ClassLoader 深入解析学习笔记(一)

在上篇转载的ClassLoader深入解析中,我们知道了类加载器的种类,以及java类文件加载的方式(双亲委托)。现就进行打包自己定义的类放到jdk的ext目录下:
测试代码
//定义一个自己的类  
public class ClassLoaderTest {  
public static void main(String[] args) {
        ClassLoader cl=ClassLoaderTest.class.getClassLoader();
        while(cl!=null){
            System.out.println(cl);
            cl=cl.getParent();//获得父类加载器的引用
        }
    System.out.println(cl);
}

控制台输出结果

结果说明:第一行表示ClassLoaderTest的类加载器是AppClassLoader
第二行表示AppClassLoader的加载器是ExtClassLoader
第三行表示 ExtClassLoader的加载器是BootStrapClassLoader 显示结果为Null,表示BootStrap不是一个普通的java类,其底层是由C++实现。已嵌入到了JVM内核当中,当JVM启动后,Bootstrap ClassLoader也随着启动,负责加载完核心类库后,并构造Extension ClassLoader和App ClassLoader类加载器。

接着我们把类ClassLoaderTest的class文件打包,放到jdk目录下:
打包步骤:在dos界面下先进入到 ClassLoaderTest文件目录下
打包命令如下

jar -cvf ClassLoaderTest.jar ClassLoaderTest.class

结果如下:
这里写图片描述
然后将打好的包放到jdk的ext 目录下,如下图
这里写图片描述

再重新设置工程的JRE System Library,把ClassLoaderTest.jar 添加到工程的library中

编译工程,再重新运行程序, 程序运行结果却不是我们期望的:
这里写图片描述
按类的双亲委托加载机制,AppClassLoader加载器先委托Bootstrap加载器, Bootstrap中找不到我们定义的这个类,就为委托ExtClassLoader,因为我们已经把ClassLoaderTest的class文件打包放到ext目录下,ExtClassLoader加载器应该找到,所以ClassLoaderTest的加载器应该是ExtClassLoader,而不应该是App加载器。
那问题纠结处在那里,在上图的执行结果中看到,ClassLoaderTest.class的包名是default,而ClassLoaderTest类我是放在包test目录下。会不会是这个问题呢?
所以重新打包,把ClassLoaderTest类包路径带上,在dos命令窗口下进入到ClassLoaderTest.class文件的包路径下打包,
命令如下:

jar -cvf ClassLoaderTest.jar test/ClassLoaderTest.class

这里写图片描述
再重新把打好的包房到ext目录下,重新设置JRE System Library;可知ClassLoaderTest包路径已经带上,如下图:
这里写图片描述
重新编译后再重新运行程序,大功告成!!!!

这里写图片描述
结果说明: 第一行表示ClassLoaderTest类的加载器是Ext加载器,
第二行表示ExtClassLoader的加载器是BootStrap加载器。
可知尽管ClassLoaderTest类是我们自定义的类,但是当我们把他放到jdk的ext目录下后,加载器只会去加载ext目录下的类,而不会重复去让App加载器去加载,第二就算我们自己定义String 类,String类的加载器也只会是BootStrap,而不是App加载器,这两点就是为什么是用双亲委托加载器的原因。
备注:文中java代码来自https://blog.csdn.net/whandgdh/article/details/80292357

更新: 在后面的学习过程中,不知道是不是因为使用jdk 8的缘故,不需要设置工程的JRE System Library,程序也能得到预期的结果。如下图所示,并没有将ClassLoaderTest.jar放到JRE System Library下面。
这里写图片描述

猜你喜欢

转载自blog.csdn.net/whandgdh/article/details/80294056