【转载】双亲委派模型

双亲委派模型是 Java 类加载器的一种工作模式,通过这种工作模式,Java 虚拟机将类文件加载到内存中,这样就保证了 Java 程序能够正常的运行起来。那么双亲委派模型究竟说的是啥呢?接下来我们一起来看。

1.类加载器

双亲委派模型针对的是 Java 虚拟机中三个类加载器的,这三个类加载器分别是:

1.启动类加载器(Bootstrap ClassLoader)

2.扩展类加载器(Extension ClassLoader)

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

如下图所示:

image.png

这 3 个类加载器的作用如下。

1.1 启动类加载器

启动类加载器(Bootstrap ClassLoader)是由 C++ 实现的,它是用来加载 \jre\lib\rt.jar 和 resources.jar 等 jar 包的,如下图所示:

image.png

接下来我们写个代码测试一下 rt 类加载器的打印:

复制代码
public class ClassLoaderExample {
    public static void main(String[] args) {
        // rt 类下的 ClassLoader 打印
        System.out.println("rt classloader:" + String.class.getClassLoader());
    }
}

以上程序的执行结果如下图所示:

image.png

问题来了,为什么打印的不是"Bootstrap ClassLoader"而是 null 呢? 这是因为启动类加载器(Bootstrap ClassLoader)是由 C++ 实现的,而这个 C++ 实现的类加载器在 Java 中是没有与之对应的类的,所以拿到的结果是 null。

1.2 扩展类加载器

扩展类加载器是用来加载 \jre\lib\ext 目录下 jar 包的,如下图所示:

image.png

接下来我们使用代码来演示一下 ext 类加载器,示例代码如下:

复制代码
public class ClassLoaderExample {
    public static void main(String[] args) {
        // ext 类下 classloader 打印
        System.out.println("ext classloader:" +
                sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader());
    }
}

以上程序的执行结果如下图所示:

image.png

1.3 应用程序类加载器

应用程序类加载器是用来加载 classpath 也就是用户的所有类的,接下来我们写代码测试一下应用程序类加载器的打印,实现代码如下:

复制代码
public class ClassLoaderExample {
    public static void main(String[] args) {
        System.out.println("application classloader:" +
                ClassLoaderExample.class.getClassLoader());
    }
}

以上程序的执行结果如下图所示:

image.png

2.双亲委派模型

双亲委派模型的执行流程是这样的: 1、当加载一个类时,会先从应用程序类加载器的缓存里查找相应的类,如果能找到就返回对象,如果找不到就执行下面流程;

2、在扩展加载器缓存中查找相应的类,如果能找到就返回对象,如果找不到就继续下面流程;

3、在启动类加载器中查询相应的类,如果找到就返回对象,如果找不到就继续下面流程;

4、在扩展加载器中查找并加载类,如果能找到就返回对象,并将对象加入到缓存中,如果找不到就继续下面流程;

5、在应用程序类加载器中查找并加载类,如果能找到就返回对象,并将对象加入到缓存中,如果找不到就返回 ClassNotFound 异常。

加载流程如下图所示:

image.png

一般"双亲"指的是"父亲"和"母亲",而在这里"双亲"指的是类加载类先向上找,再向下找的流程就叫做双亲委派模型。

3.优缺点分析

3.1 优点

双亲委派模型的优点有两个: 1、安全。 2、避免重复加载。

3.1.1 安全

在安全方面的表现时,当使用双亲委派模型时,用户就不能伪造一些不安全的系统类了,比如 jre 里面已经提供了 String 类在启动类加载时加载,那么用户自定义再自定义一个不安全的 String 类时,按照双亲委派模型就不会再加载用户定义的那个不安全的 String 类了,这样就可以避免非安全问题的发生了。

3.1.2 避免重复加载

使用双亲委派模型也可以避免一个类被重复加载,当一个类被加载之后,因为使用的双亲委派模型,这样不会出现多个类加载器都将同一个类重复加载的情况了。

3.2 缺点

双亲委派模型的典型问题是加载 SPI 实现类的场景,比如 JNDI(Java Naming and Directory Interface,Java 命名与目录接口)服务,它的代码由启动类加载器去加载(在 JDK 1.3 时放进 rt.jar),但 JNDI 的目的就是对资源进行集中管理和查找,它需要调用独立厂商实现部部署在应用程序的 classpath 下的 JNDI 接口提供者(SPI, Service Provider Interface)的代码,但启动类加载器不可能"认识"之些代码,这就双亲委派模型的问题,JDBC 也是同样的问题。

总结

双亲委派模型是和 Java 中多个类加载器(启动类加载器、扩展加载器、应用程序类加载器)的运行规则,通过这个(双亲委派模型)规则可以避免类的非安全问题和类被重复加载的问题,但它也遇到了一些问题,比如 JNDI 和 JDBC 不能通过这个规则进行加载,它需要通过打破双亲委派的模型的方式来加载。

相关推荐
渣哥1 小时前
原来 Java 里线程安全集合有这么多种
java
间彧1 小时前
Spring Boot集成Spring Security完整指南
java
间彧1 小时前
Spring Secutiy基本原理及工作流程
java
Java水解2 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆5 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学5 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole5 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端
华仔啊5 小时前
基于 RuoYi-Vue 轻松实现单用户登录功能,亲测有效
java·vue.js·后端
程序员鱼皮6 小时前
刚刚 Java 25 炸裂发布!让 Java 再次伟大
java·javascript·计算机·程序员·编程·开发·代码