类加载 - 被谁加载

2019-08-03  本文已影响0人  武曌思

类加载包含两部分:一部分是被谁加载,另一部分是如何加载。
被谁加载是指 ClassLoader 的双亲委派模型,如何加载是指类的加载过程。
这篇博客介绍双亲委派模型,特别感谢 @书呆子Rico老师 的博客


ClassLoader 结构核心思想

class ClassLoader {
    /**
     * 父加载器
     */
    ClassLoader parent;
    /**
     * 已经加载的 class
     * 这个属性是我假想的,为了配合 {@link #findLoadedClass} 的猜想
     */
    Map<String, Class> loadedClasses;

    /**
     * 尝试从已经加载的类中寻找,如果没有返回 null
     * 真实的实现是 native 方法,我猜想是存了一个类名到类实例的映射,如下
     */
    Class<?> findLoadedClass(String name){
        return loadedClasses.get(name);
    }

    /**
     * 当前类加载器尝试去加载一个类,内部实现就是类的加载过程
     * 为什么说尝试?因为当前类加载器可能无法加载这个类,会返回 null
     */
    Class<?> findClass(String name){}

    /**
     * 双亲委派模型的实现,也是类加载的直接入口
     */
    Class<?> loadClass(String name){}
}

双亲委派模型

当类加载器尝试加载一个类时,会首先查看自己加载过的类。如果没有查找到,不是马上去加载,而是去询问父加载器(这是一个递归的过程)。如果父加载器也没有加载,自己才会加载。双亲委派模型是通过组合的方式实现的,不是继承

双亲委派模型图

双亲委派实现自己实现的伪代码

Class<?> loadClass(String name) {
    // 查找自己加载过的类
    Class<?> loadedClass = findLoadedClass(name);
    if (loadedClass == null) {
        // 尝试让父类加载
        if (parent == null) {
            // 调用 BootstrapClassLoader 去加载,后面介绍 Java 类加载器的层级结构
        } else {
            loadedClass = parent.loadClass(name);
        }
        // 如果父类没有加载,自己加载
        if (loadedClass == null) {
            loadedClass = findClass(name);
        }
    }
    // 返回最终结果,此时还有可能为 null
    // 如果当前类加载器有子加载器,则子加载器还会尝试加载,否则就会包 ClassNotFoundException
    return loadedClass;
}

双亲委派作用


Java 类加载器层级结构

如双亲委派模型图中展示的,Java 中现有类加载器分三层。

上一篇下一篇

猜你喜欢

热点阅读