JVM系列之(七)双亲委派模型

概要

  • 应用程序都是由三种类加载器相互配合进行加载的,如果有必要,还可以加入自己定义的类加载器。下图展示的类加载器之间的层次关系,称为类加载器的双亲委派模型(ParentsDelegationModel)。该模型要求除了顶层的启动类加载器外,其余的类加载器都应有自己的父类加载器,这里类加载器之间的父子关系一般通过组合(Composition)关系来实现,而不是通过继承(Inheritance)的关系实现。
    JVM系列之(七)双亲委派模型_第1张图片

(一)工作过程

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载,而是把这个请求委派给父类加载器,每一个层次的加载器都是如此,依次递归。因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成此加载请求(它搜索范围中没有找到所需类)时,子加载器才会尝试自己加载。

(二)好处

使用双亲委派模型来组织类加载器之间的关系,使得 Java 类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类 java.lang.Object,它存放在 rt.jar 中,无论哪个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此 Object 类在程序的各种类加载器环境中都是同一个类。相反,如果没有双亲委派模型,由各个类加载器自行加载的话,如果用户编写了一个称为java.lang.Object 的类,并放在程序的 ClassPath 中,那系统中将会出现多个不同的 Object 类,程序将变得一片混乱。如果开发者尝试编写一个与 rt.jar 类库中已有类重名的 Java 类,将会发现可以正常编译,但是永远无法被加载运行。

(三)实现

protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException{
    // 先检查请求的类是否已经被加载过了
    Class c = findLoadedClass(name);
    if(c == null) {
        try{
            if(parent != null) {
                c = parent.loadClass(name, false);
            } else{
                c = findBootstrapClassOrNull(name);
            }
        } catch(ClassNotFoundException e) {
            // 如果父类加载器抛出 ClassNotFoundException,说明父类加载器无法完成加载请求
        }
        if(c == null) {
            // 如果父类加载器无法完成加载请求,再调用自身的 findClass() 来进行加载
            c = findClass(name);
        }
    }
    if(resolve) {
        resolveClass(c);
    }
    return c;

(四)如何打破双亲委派模型

参考:[https://blog.csdn.net/zhangcanyan/article/details/78993959]

你可能感兴趣的:(JVM,JVM)