双亲委派模型

一、什么是双亲委派模型

  简单来说,就是当一个类加载器被调用的loadClass方法之后,不会直接就加载这个class,而是会先将加载任务向上(父加载器)递交,让父类加载器尝试加载,直到最顶层类加载器,然后再依次向下加载,直到能够加载返回。

1 public Class<?> loadClass(String name) throws ClassNotFoundException {
2         return loadClass(name, false);
3     }
 1 protected Class<?> loadClass(String name, boolean resolve)
 2         throws ClassNotFoundException
 3     {
 4         synchronized (getClassLoadingLock(name)) {
 5             // First, check if the class has already been loaded
 6             Class<?> c = findLoadedClass(name);
 7             if (c == null) {
 8                 long t0 = System.nanoTime();
 9                 try {
              //有父类加载器,直接往上抛
10 if (parent != null) { 11 c = parent.loadClass(name, false); 12 } else {
               //没有父类加载器,直接抛给bootstrap类加载器
13 c = findBootstrapClassOrNull(name); 14 } 15 } catch (ClassNotFoundException e) { 16 // ClassNotFoundException thrown if class not found 17 // from the non-null parent class loader 18 } 19          //如果都不能加载,那就调用自身的findClass()进行加载 20 if (c == null) { 21 // If still not found, then invoke findClass in order 22 // to find the class. 23 long t1 = System.nanoTime(); 24 c = findClass(name); 25 26 // this is the defining class loader; record the stats 27 sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); 28 sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); 29 sun.misc.PerfCounter.getFindClasses().increment(); 30 } 31 } 32 if (resolve) { 33 resolveClass(c); 34 } 35 return c; 36 } 37 }

从上面的ClassLaod的JDK源码中,可以看出,一个类在加载的时候,是双亲委派的形式进行。

二、打破双亲委派模型

  在一些场景下,我们需要绕过双亲委派模型,例如在不停止服务的前提下,更新或增加某个模块的功能,也就是热部署,而热部署首先就要卸载掉该模块所有Class的类加载器。然后根据上面的源代码我们可以知道,loadClass()方法中,代码顺序是先将任务抛给父类加载器,最后才是执行自己的findClass(),那么只需要重写ClassLoad的loadClass()方法,将顺序颠倒一下,或者对加载的类全限定名作出判断筛选再加载,就可以实现破坏双亲委派模型的效果。

 

posted @ 2021-01-04 22:03  huang1993  阅读(325)  评论(0)    收藏  举报