fenixsoft / jvm_book

《深入理解Java虚拟机(第3版)》样例代码&勘误
1.35k stars 222 forks source link

双亲委派模型的工作过程 #189

Open Ynjxsjmh opened 2 years ago

Ynjxsjmh commented 2 years ago

双亲委派模型 这一小节中 图7-2 类加载器双亲委派模型 是像下图这样的

image

下面是让我糊涂的几段文字

图7-2中展示的各种类加载器之间的层次关系被称为类加载器的“双亲委派模型(Parents Delegation Model)”。双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应有自己的父类加载器。不过这里类加载器之间的父子关系一般不是以继承(Inheritance)的关系来实现的,而是通常使用组合(Composition)关系来复用父加载器的代码。 ... 双亲委派模型的工作过程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载。 ... 这段代码的逻辑清晰易懂:先检查请求加载的类型是否已经被加载过,若没有则调用父加载器的loadClass()方法,若父加载器为空则默认使用启动类加载器作为父加载器。假如父类加载器加载失败,抛出ClassNotFoundException异常的话,才调用自己的findClass()方法尝试进行加载。

问题一:

这一小节没有定义“类加载器之间的父子关系”是什么,我猜测 图7-2 类加载器双亲委派模型 里面想表示的是这种关系,箭头指向的是父加载器。但是文章中只说了“图7-2中展示的各种类加载器之间的层次关系”,这种“层次关系”是“父子层次关系”么?

问题二:

“代码逻辑”里面有“若没有则调用父加载器的loadClass()方法,若父加载器为空则默认使用启动类加载器作为父加载器”这样一段话。

“双亲委派模型的工作过程”里却没有提到“父加载器”为空的情况,只提到“父加载器反馈自己无法完成这个加载请求”这种情况。

问题三:

假如父类加载器加载失败,抛出ClassNotFoundException异常的话,才调用自己的findClass()方法尝试进行加载。

代码里在父加载器为空时,调用了 findBootstrapClassOrNull 方法,从方法名上看返回值可能是 null,此时也会抛出 ClassNotFoundException 异常么?如果不会抛出的话,假如父类加载器加载失败,抛出ClassNotFoundException异常的话,才 中前两小句的关系应该是 而不是递进的关系。

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;
}