双亲委派模型 ╰+攻爆jí腚メ 2021-09-25 11:08 370阅读 0赞 围绕这四个问题去回答一下: 1. 什么是双亲委派模型 2. 为什么会有双亲委派模型 3. 可以打破双亲委派模型? 4. 为什么要打破双亲委派模型? ## 一、什么是双亲委派模型? ## 双亲委派模型是在jdk1.2后引入,首先先看看类加载机制,如下图: ![1.png][] ### Bootstrap ClassLoader (启动类加载器) ### Bootstrap ClassLoader,启动类加载,默认加载的是jdk\\lib目录下jar中诸多类; 这个路径可以使用 -X bootclasspath参数指定。 ### Extension ClassLoader (扩展类加载器) ### Extension ClassLoader,扩展类加载器,默认加载jdk\\lib\\ext\\目录下jar中诸多类; 这个路径可以使用 java.ext.dirs系统变量来更改。 ### Application ClassLoader (应用程序类加载器) ### Application ClassLoader,应用程序类加载器,负责加载开发人员所编写的诸多类。 ### User ClassLoader (自定义类加载器) ### 自定义类加载器,当存在上述类加载器解决不了的特殊情况,或存在特殊要求时,可以自行实现类加载逻辑。 双亲委派模型顾名思义就是每一个类加载器(classLoader)收到一个类加载请求,都不会先自己去加载,而是委托给自己的父类加载,如果父类加载器还存在它的父类加载器,则继续向上委托,直到达到最顶层的父类加载器,从最顶层的父类加载器开始进行类的加载,如果最顶层的类加载器找不到类的路径,又交给子类加载进行加载,依次进行递归,通俗地说,如下面的例子: * 假设用户刚刚写的Test类想进行加载,这个时候首先会发送给应用程序类加载器AppCloassLoader; * 然后AppClassLoader并不会直接去加载Test类,而是会委派于父类加载器完成此操作,也就是ExtClassLoader; * ExtClassLoader同样也不会直接去加载Test类,而是会继续委派于父类加载器完成,也就是BootstrapClassLoader; * BootstrapClassLoader这个时候已经到顶层了,没有父类加载器了,所以BootstrapClassLoader会在jdk/lib目录下去搜索是否存在,因为这里是用户自己写的Test类,是不会存在于jdk下的,所以这个时候会给子类加载器一个反馈。 * ExtClassLoader收到父类加载器发送的反馈,知道了父类加载器并没有找到对应的类,爸爸靠不住,就只能自己来加载了,结果显而易见,自己也不行,没办法,只能给更下面的子类加载器了。 * AppClassLoader收到父类加载器的反馈,顿时明白,原来爸爸虽然是爸爸,但是他终究不能管儿子的私事,所以这时候,AppClassLoader就自己尝试去加载。 * 结果,就这样成功了,走了一大圈,兜兜转转还是自己干。 这就是双亲委派模型。 ## 二、为什么会有双亲委派模型? ## 这样做的好处是java随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存放在rt.jar中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户自己编写了一个称为java.lang.object的类,并放在程序的ClassPath中,那系统中将会出现多个不同的Object类,Java类型体系中最基础的行为也就无法保证,应用程序也将会变得一片混乱。 其次是考虑到安全因素。假设通过网络传递一个名为java.lang.Integer的类,通过双亲委托模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer,而直接返回已加载过的Integer.class,这样便可以防止核心API库被随意篡改。 ## 三、可以打破双亲委派模型? ## 可以打破,有以下两种方式: 1. 自定义类加载器,重写loadClass方法; 2. 使用线程上下文类加载器; ## 四、为什么要打破双亲委派模型? ## 在JDBC 4.0之后实际上我们不需要再调用Class.forName来加载驱动程序了,我们只需要把驱动的jar包放到工程的类加载路径里,那么驱动就会被自动加载。 这个自动加载采用的技术叫做SPI,数据库驱动厂商也都做了更新。可以看一下jar包里面的META-INF/services目录,里面有一个java.sql.Driver的文件,文件里面包含了驱动的全路径名。 使用上,我们只需要通过下面一句就可以创建数据库的连接: Connection con = DriverManager.getConnection(url , username , password ) ; ** 因为类加载器受到加载范围的限制,在某些情况下父类加载器无法加载到需要的文件,这时候就需要委托子类加载器去加载class文件。** JDBC的Driver接口定义在JDK中,其实现由各个数据库的服务商来提供,比如MySQL驱动包。DriverManager 类中要加载各个实现了Driver接口的类,然后进行管理,但是DriverManager位于 $JAVA\_HOME中jre/lib/rt.jar 包,由BootStrap类加载器加载,而其Driver接口的实现类是位于服务商提供的 Jar 包,**根据类加载机制,当被装载的类引用了另外一个类的时候,虚拟机就会使用装载第一个类的类装载器装载被引用的类。**也就是说BootStrap类加载器还要去加载jar包中的Driver接口的实现类。我们知道,**BootStrap类**加载器默认只负责加载 $JAVA\_HOME中jre/lib/rt.jar 里所有的class,所以需要由子类加载器去加载Driver实现,这就**破坏了双亲委派模型**。 查看DriverManager类的源码,看到在使用DriverManager的时候会触发其静态代码块,调用 loadInitialDrivers() 方法,并调用ServiceLoader.load(Driver.class) 加载所有在META-INF/services/java.sql.Driver 文件里边的类到JVM内存,完成驱动的自动加载。 [1.png]: /images/20210923/690d256821e54894b9191dbacd9e1c8f.png
相关 破坏双亲委派模型 一 概述 双亲委派模型并不是一个具有强制性约束的模型,而是Java设计者推荐给开发者的类加载方式。Java中的大部分类的加载器都遵循这个模型。例外的是,直到Java模块化 ﹏ヽ暗。殇╰゛Y/ 2022年12月08日 04:46/ 0 赞/ 204 阅读
相关 双亲委派模型 双亲委派模型(图解) ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9 冷不防/ 2022年11月10日 10:43/ 0 赞/ 189 阅读
相关 双亲委派模型 一 定义与本质 类加载器用来把类加载到 Java 虚拟机中。从 JDK1.2 版本开始,类的加载过程采用双亲委派机制,这种机制能更好地保证 Java 平台的安全。 1 左手的ㄟ右手/ 2022年09月06日 14:19/ 0 赞/ 211 阅读
相关 双亲委派模型 说道双亲委派模型,就要从类加载器说起。。。。。。。。。。。 [Java][]虚拟机类加载过程是把Class类文件加载到内存,并对Class文件中的数据进行校验、转换解析和初始 亦凉/ 2022年07月12日 13:26/ 0 赞/ 224 阅读
相关 双亲委派模型 其实,双亲委派模型并不复杂。自定义类加载器也不难!随便从网上搜一下就能搜出一大把结果,然后`copy`一下就能用。但是,如果每次想自定义类加载器就必须搜一遍别人的文章,然后复制 落日映苍穹つ/ 2022年05月09日 16:56/ 0 赞/ 243 阅读
相关 双亲委派模型 双亲委派模型 类与类加载器 双亲委派模型 虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到 野性酷女/ 2022年03月10日 14:28/ 0 赞/ 261 阅读
相关 双亲委派模型 双亲委派模型 双亲委派模型简介 双亲委派模型实现源码分析 双亲委派模型的好处 双亲委派模型简介 每一个类都有一个对应它的类加载器。系统中的类加载 不念不忘少年蓝@/ 2021年11月10日 14:28/ 0 赞/ 625 阅读
相关 双亲委派模型 双亲委派模型(Since JDK.2): ![这里写图片描述][70] 从虚拟机的角度来看,类加载器主要分为启动类加载器(Bootstrap Classloader)和 £神魔★判官ぃ/ 2021年09月26日 14:36/ 0 赞/ 594 阅读
相关 双亲委派模型 围绕这四个问题去回答一下: 1. 什么是双亲委派模型 2. 为什么会有双亲委派模型 3. 可以打破双亲委派模型? 4. 为什么要打破双亲委派模型? 一、 ╰+攻爆jí腚メ/ 2021年09月25日 11:08/ 0 赞/ 371 阅读
还没有评论,来说两句吧...