双亲委派模型

双亲委派模型

Java基础类库给我们提供了几种类加载器,这几种类加载器的关系如图4.5所示。

图4.5 JDK提供的几种类加载器

BootstrapClassLoader:负责加载JDK提供的基础类库,基础类库编译后的rt.jar包位于 $JAVA_HOME/lib目录下。该类加载器由C代码实现,也叫启动类加载器。

ExtClassLoader:负责加载JVM扩展类,比如内置的js引擎、xml解析器等等,这些库名通常以javax开头,它们的jar包位于 $JAVA_HOME/lib/ext目录。

AppClassLoader:应用程序加载器,负责加载classpath路径中的jar包和目录,我们编写的代码以及使用的第三方jar包通常都是由它来加载。

这几种类加载的关系并非继承关系,而是通过持有一个父加载器的引用,在外部调用loadClass方法时,先委托父加载器去加载,在父加载器抛出ClassNotFoundException异常时,再由自己去加载,如果还是加载不到类,再往上抛出ClassNotFoundException异常,这就是双亲委派模型。双亲委派的实现如代码清单4-12所示。

代码清单4-12 双亲委派的实现

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            ......
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }
                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);
                    ......
                }
           ......
            return c;
        }
    }

如果想要打破双亲委派模型,只需要在自实现的类型加载器中重写该方法,去掉try-catch部分的逻辑即可。