1、引言
看了王森老师的《java深度历险》(我的资料中有PDF版下载),在讲到加载器委托模型时(p69),按照书上的指示,做实验,但是不成功,非常奇怪。包括我查阅了很多资料,发现都不能达到和书中讲的效果。
2、现象再现
我现在来讲讲我对书中的理解(有误的话,请谅解)。书中讲到classpath,默认指的是program files\java\jre\xxx目录,而bootstrap loader的默认路径是jre\classes(默认无此目录,用户可自行添加),ext loader默认寻找类是在jre\lib\ext\classes目录。
上面是基本的概念,至于bootstrap classloader及ext classloader等基本可以在我的贴的参考资料中找到详细的说明。
我按照上面的理解,在我的idea环境下,编写了2个java文件,一个TestMain.java,TestLib.java。内容如下所示:
TestMain.java
public class TestMain { public static void main(String[] args) { TestLib testLib = new TestLib(); testLib.disp(); } }
TestLib.java
public class TestLib { public void disp(){ ClassLoader currentLoader = this.getClass().getClassLoader(); if(currentLoader== null){ System.out.println("current loader is bootstrap loader"); return; }else{ System.out.println("test lib class loader:"+currentLoader); System.out.println("test lib parent class loader:"+currentLoader.getParent()); } } }
然后编译上述文件,并将TestLib.class入到program files\jre\classes目录和program files\jre\lib\ext\classes目录,发现结果始终如下:
test lib class loader:sun.misc.Launcher$AppClassLoader@18b4aac2
test lib parent class loader:sun.misc.Launcher$ExtClassLoader@73a28541
百思不得其解呀,相信大家在查相关资料时(包手我罗列的参考资料也是这么说的)。
3、解惑
后面我使用process monitor这个相当底层的工具一看(因为自己有这方面的功底,嘿嘿,包括我调试过ClassLoader的源码,但是没有找到原因),才发现如下图所示内容:
从上图可以发现,java class loader是从jdk\jre\classes目录下查找,而不是jre\classes查找。相信大家如果是要了解java委托机制的人,不可能只安装jre,而不安装jdk的。有了这个发现,我觉得问题就好办了,只需要将TestLib.class文件拷贝到jdk\jre\classes目录下就可以了。拷贝后,
测试,如下所示:
上述这个是使用bootstrap classloader加载的。
下面拷贝到jdk\jre\lib\ext\classes目录下,如下所示:
测试结果如下
所有的实验和书中及参考的例子都一样了。
4、总结
从上面可以看出:
(1)、书中或资料中没有将我们当作是一个java码农来看待,导致了这个问题。当然,如果设置了classpath为program files\jre,则不会出现我所说的问题。我只设置了java_home的环境变量,没有设置classpath的环境变量。
(2)、只要我们足够细心,包括对jvm运行机制了解,则可以知道错误的所在。如我这里是使用了process monitor这个工具,其实大家也可以在TestMain.java中写如下语句,查看当前的classpath,如下所示:
URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs(); for (int i = 0; i < urls.length; i++) { System.out.println(urls[i].toExternalForm()); }
结果如下所示:
从上面可以看到,class loader是从jdk\jre目录加载的。甚至我们可以使用java -verbose:class查看加载的路径。
5、参考资料
(1)、《java深度历险》,王森著,华中科技大学出版社出版,2002年10月出版,极力推荐大家看一下。
(2)、https://blog.csdn.net/wangyang665/article/details/38636985,java类加载的委托机制
(3)、https://blog.csdn.net/yue7603835/article/details/7243869,Java类加载器 以及类加载器的委托模型
希望上述让你能彻底了解java类加载器的加载过程。也感谢王老师编写的书及网上无数同仁的正确或错误的引导。哈哈。我这篇文章也有可能是有误导的。