首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

通过自定义类加载器来验证双亲委托机制

上一篇文章我们知道了类加载器通过组合方式实现了双亲委托,那么类又是如何具体加载的呢?

类加载过程

回顾下类加载的源码,如下图:

上一篇文章中自定义的类加载器直接重写了loadClass,打乱了类加载的双亲委托机制,今天需要在不破坏这个机制下自定义!

从源码中可以看出如果在parent最终不能加载的情况下,会来到第3步由当前加载器来加载,而第3步最关键的代码就是“ c = findClass(name)”。我们先找到应用类加载器Launcher.AppClassLoader并没有findClass(name)方法,不过它的父类URLClassLoader实现了findClass方法,方法代码如下图:

可以看到这个方法在获取要加载类的正真文件,继续跟definClass方法最后会调用ClassLoader.defineClass,在这个方法里面会调用一个defineClass1的本地方法!

自定义类加载器

从以上分析出我们如果想自定义一个类加载器,同时不破坏双亲委托机制,最关键的是重写findClass方法,所以我们就可以自定义实现类加载器了,代码如下图:

自定义的classLoader给他新增了一个名称属性,并且重写了findClass,同时在findClass方法第一行打印了类加载名称和加载的类名称。

写一个测试方法并运行,运行结果如下图:

根据打印结果可以判断并没有运行findClass方法,这是什么原因呢?

在自定义的类加载器中构造函数没有显示的执行super()就会默认执行父类的默认构造函数,也就是ClassLoader的默认构造函数,它设置的parent是AppClassLoader

而我们加载的类“com.dggcc.test.classload.ClassLoadTest”在当前工程下,是可以被AppClassLoader所加载的,所以最终并不会执行MyClassLoader的findClass方法。

对类加载器进行改造,使他去加载指定文件夹下的文件,改造后代码如下图:

在加载器中添加一个属性path,同时查找class文件的时候只在这个文件下加载,测试代码如下图:

首先要把ClassLoadTest.class移到你想加载的路径下,然后要把把项目下对应的ClassLoadTest.class文件删除,否则在加载的时候AppClassLoader还是能找到“com.dggcc.test.classload.ClassLoadTest”对应的class文件,能够加载成功。删除后由于系统自带的加载器都不能加载这个类,最终由我们自定义的类加载加载,从打印结果可以验证我们的结论!

测试验证结论

通过自定义类加载我们就可以很方便的验证之前的一些结论,测试代码如下图:

可以看到myclassLoad1对同一个类加载2次,但是真正只加载了一次,并且根据类的hashCode也可以看出来是同一个class对象。而如果再次new一个myclassLoad2出来对同一个class文件加载,就再次加载了一次,并且hashCode也不同不是同一个class对象!

可以得出结论:同一个类只会被同一个类加载器加载一次,不同的类加载器加载同一个class文件加载出来的class对象也不相同!

我们对代码再次改造进行测试,改造代码如下图:

新建了一个构造函数用来设置parent属性,通过结果可以看到类只被加载了一次,这是因为myclassLoad1作为了myclassLoad2的parent。所以myclassLoad2在加载类的时候会去myclassLoad1找是否加载。如果加载了myclassLoad2就不会再加载了!

如果在myclassLoad2之前不加载类,测试代码如下图:

可以看到正真加载类的还是myclassLoad1,也就是双亲委托机制!

‍总结‍

结合上一篇我们知道重写loadClass方法可能会破坏双亲委托机制,而只重写findClass则不会,同时可以实现去加载其他地方的class文件。

通过自定义类加载我们再次验证了类的加载机制,同一个类只会被同一个类加载器加载一次,不同的类加载器加载同一个class文件加载出来的class对象也不相同!并且再次验证了双亲委托加载类。

Java程序员日常学习笔记,如理解有误欢迎各位交流讨论!

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200521A0Q97J00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券