为啥说java spi破坏双亲委派模型( 二 )


System.out.println(java.sql.Connection.class.getClassLoader());会发现返回的null。说明Connection自己是被Bootstrap ClassLoader加载的。
综上,并没有说Bootstrap ClassLoader加载了个第三方库或者Application ClassLoader加载了JDK的库的情况发生。
所以能否请题主给出具体哪里写了“SPI破坏双亲委派模型“?我再仔细看看是不是前后哪里谁理解错了。可能是我错了,也可能是那个参考错了。

■网友
这个问题在之前粗略的了解过,知道有这么回事,也不难理解,但是究其细节,很多点并非足够经得起推敲。现在就来抽丝剥茧梳理一遍。

类加载器(classloader)先从类加载器说起,凡事先问是什么,首先什么是类加载器?
我们知道,一个 *.java 的代码源文件要执行起来之前,必须通过 javac 构建抽象语法树并编译成字节码,字节码仍然是不能被机器所识别,那么一个 .class 文件要被机器识别并执行的前提就是将字节码转化成机器码加载到内存里,这一转化过程就是类加载的执行过程。

为啥说java spi破坏双亲委派模型

当然,这整个过程细节并非这个问题的讨论重点。
类加载器便是在在这个过程里的加载阶段起作用,负责将 .class 文件字节码提取出来,转化成二进制字节流。
(但是这离成为真正的类还有十万八千里。。。)
一个Java应用中通常存在三个类加载器(Classloader):
Bootstrap Classloader 启动类加载器:负责加载\u0026lt;JRE\u0026gt;/lib 下的核心类库,此加载器本身内嵌于JVM,在 Java 中找不到具体的引用;Extension Classloader 扩展类加载器:负责加载\u0026lt;JRE\u0026gt;/lib/ext 下的扩展类库;Application Classloader 系统应用类加载器:负责-classpath 指定路径类库加载。为啥说java spi破坏双亲委派模型

【为啥说java spi破坏双亲委派模型】 他们三者并非典型的继承关系,而是子指派父为自己的 parent。
(这里有个源码细节,由于启动类加载器是内嵌于 JVM 且无法被引用,因此 Extension Classloader 指派 parent 为 null,即等同于指派启动类加载器为自己的父加载器)
为了有足够灵活性,类加载器也是允许自定义的。这不禁思考,这么多类加载器之间是怎么协调类加载任务的?
这就引出了本文的重点,双亲委派模型。

双亲委派(parents deletation model)双亲委派模型是什么?
The Java platform uses a delegation model for loading classes. The basic idea is that every class loader has a "parent" class loader. When loading a class, a class loader first "delegates" the search for the class to its parent class loader before attempting to find the class itself.由于翻译问题,这里双亲的 “双” 并没有太多特殊含义,双亲就是父母。简单来说,当一个类加载器得到一个类加载任务 t 的时候,首先会委派其 parent A 去加载,A 拿到任务后,也会进一步委派到 A 的 parent B。层层向上递归直到委派到启动类加载器。
但我们知道,每个 classloader 负责的加载域是不一样的,启动类加载器需根据 t 给出的类全限定名(如 com.Test)在其所负责的域里搜寻此类字节码,如果找到,则加载之;如果找不到,则表示无法加载,把代理权限往下(父-\u0026gt;子)转移,直到某个加载器在负责的加载域中找到该类为止。

这一逻辑的代码实现是这样的:
java.lang.ClassLoader#loadClass(java.lang.String, boolean)


推荐阅读