java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java双亲委派模型

详解Java类加载机制中的双亲委派模型

作者:小威要向诸佬学习呀

Java的双亲委派模型是一种类加载机制,它用于保证Java类的安全性和稳定性,在这个模型中,当一个类需要被加载时,Java虚拟机会先检查自己是否已经加载了该类,本文就给大家讲解一下Java类加载机制中的双亲委派模型,需要的朋友可以参考下

Java中的类加载器

在介绍双亲委派模型之前,首先先介绍下Java中的类加载器。

启动类加载器(Bootstrap ClassLoader)

首先先介绍下类加载器中的重量级器物,就是大名鼎鼎--启动类加载器。

为什么说他是重量级的恩,因为它是Java类加载器层次结构的最顶层,由虚拟机实现,用于加载Java核心类库,如java.lang和java.util等。

既然是最顶层的类加载器,我们就康康它有什么作用:

启动类加载器是由C/C++编写的,无法直接在Java代码中获取其引用。 它负责加载Java运行时环境所需的基本类。

扩展类加载器(Extension ClassLoader)

接着我们看一下Java加载器中的第二号人物--扩展类加载器。

扩展类加载器是由Java编写的,它是启动类加载器的子类。 它负责加载Java扩展类库,位于jre/lib/ext路径下的JAR文件。 扩展类加载器可以通过java.ext.dirs系统属性来指定其他目录作为扩展类库的路径。

应用程序类加载器(Application ClassLoader)

接着介绍最底层的加载器--应用程序类加载器。

应用程序类加载器是Java类加载器层次结构的最底层,也称为系统类加载器。 它负责加载应用程序类路径(Classpath)下的类,包括开发者自己编写的类和第三方库。 应用程序类加载器可以通过-classpath或-cp选项来指定加载类的路径。

自定义类加载器(Custom ClassLoader)

除了上述系统类的加载器,我们开发者还可以自定义加载器-惊不惊喜,意不意外。

自定义类加载器是开发者根据需求编写的自定义加载器,继承自ClassLoader类。 它可以根据特定的加载规则和需求,从不同的来源加载类,比如本地文件系统、网络等。 自定义类加载器需要实现findClass()方法,指定类的加载规则,然后通过defineClass()方法加载类的字节码。

双亲委派模型

看到这里,上我们的重头菜,这块知识是面试中的重点内容。

双亲委派(Parent Delegation)是Java类加载机制中一种重要的实现方式,它通过一种递归的方式在类加载器之间建立了父子关系,并且定义了类加载的优先级。该模型主要用于解决类加载的冲突和隔离问题,保证Java应用程序的稳定性和安全性。

在Java类加载机制中,每个类加载器都有一个父加载器。当一个类加载器需要加载一个类时,它首先会委托给它的父加载器进行加载。只有当父加载器无法加载时,子加载器才会尝试加载。这种递归的委派模型可以形成一个类加载器的层次结构,称为类加载器树。

我看了《深入理解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) {
            // 如果父类加载器也无法找到类,则尝试自己加载
            c = findClass(name);
        }
    }
    if (resolve) {
        resolveClass(c);
    }
    return c;
}

在上面的源码中,我们可以看到双亲委派机制的体现。当loadClass方法被调用时,首先会检查该类是否已经被加载。如果没有加载,那么会按照以下步骤进行处理:

如何打破双亲委派模型

其实双亲委派模型并不是具有强制性约束的模型,虽然它有助于保证类的隔离和加载的顺序,但有时候我们可能需要打破这种机制,比如我们在特殊情况下需要自定义类加载逻辑或实现热部署的时候。

上周面试问道了这个问题,所以在这里也介绍几种打破Java中双亲委派机制的方法:

综上所述,不正确地使用或滥用这些方法可能导致类加载冲突、安全问题以及代码的不稳定性 ,因此我们还需要在明确的需求和充分的理解下使用(面试会背诵就行【手动狗头】)。

以上就是详解Java类加载机制中的双亲委派模型的详细内容,更多关于Java双亲委派模型的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文