自定义类加载器,有点简单呐~

157 阅读2分钟

「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」。

前言

前面的几篇文章主要讲了类加载的基本信息打破双亲委派模型的应用,这中间都需要通过自定义类加载器来实现。

那么我们该如何创建自定义类加载器,它又是怎么打破双亲委派的呢?这边车辙给大家理一下思路:

image.png 前提都是继承ClassLoader,里面有两个方法:loadClass(),findClass()。

  1. 调用loadClass()方法,这个方法的功能就是加载指定的类。首先会去判断是否存在父类,那么我们是否可以重写loadClass方法,不去调用父类加载器的loadClass方法,而是首先自己去加载。这样不就达成目标了。
  2. 调用findClass()方法,这个方法的功能是找到指定的类。首先会去查询父类加载器的路径是否存在该类,那么如果我能将类放在几个父类加载器无法加载的路径,最终还会下沉到自定义类加载器中。

第一步:继承ClassLoader

image.png 如果需要自定义类加载器,可以继承ClassLoader。当然UrlClassLoader也是可行的,只是加载时候的入参就不同了。

第二步(选择1):重写loadClass方法

image.png 重写loadClass方法,使自定义类加载器率先加载,如果加载失败,try-catch兜底,从而打破双亲委派模型。

这边额外提一点:判断类是否已加载的主体是类加载器,也就是类尽管在A加载器加载过了,但是在B加载器中也是属于未加载过的。在B加载器通过GC回收后,B加载器加载的类也就有机会被卸载掉了。热加载也就是通过这一点来实现的。

第二步(选择2):重写findClass方法时

image.png image.png 重写findClass方法。这边将BigData类放到了桌面上,由于AppClassLoader等加载器的加载路径不在桌面上,因此无法加载BigData类,最终还是会由我们的自定义类加载器加载。

结尾

上文简单讲述了自定义类加载器的实现,可以通过重些loadClass或者findClass方法,推荐前者哈。

这边留下一个问题:如果我使用类加载器加载A类后, 在new A()时,使用的是哪个A呢?AppClassLoader.A or 自定义类加载器.A?