有哪些实际场景是需要打破双亲委派模型的?

JNDI 服务,它的代码由启动类加载器去加载,但 JNDI 的目的就是对资源进行集中管理和查找,它需要调用独立厂商实现并部署在应用程序的 classpath 下的 JNDI 接口提供者(SPI, Service Provider Interface) 的代码,但启动类加载器不可能“认识”之些代码,该怎么办?

为了解决这个困境,Java 设计团队只好引入了一个不太优雅的设计:**线程上下文类加载器(Thread Context ClassLoader)。这个类加载器可以通过 java.lang.Thread 类的 setContextClassLoader() 方法进行设置,如果创建线程时还未设置,它将会从父线程中继承一个;如果在应用程序的全局范围内都没有设置过,那么这个类加载器默认就是应用程序类加载器。有了线程上下文类加载器,JNDI 服务使用这个线程上下文类加载器去加载所需要的 SPI 代码,也就是父类加载器请求子类加载器去完成类加载动作,这种行为实际上就是打通了双亲委派模型的层次结构来逆向使用类加载器,已经违背了双亲委派模型,但这也是无可奈何的事情。Java 中所有涉及 SPI 的加载动作基本上都采用这种方式,例如 JNDI、JDBC、JCE、JAXB 和 JBI 等。

发表评论

后才能评论

评论(5)

  • 一蓑烟雨 普通 2022-09-29 9:27 下午

    以JDBC为例,它的代码在rt.jar中,由启动类加载器去加载,但它需要调用厂商实现的SPI代码,这些代码部署在ClassPath下面。
    根据双亲委派模型,启动类加载器无法直接委派应用程序类加载器(Application ClassLoader)来加载SPI的实现代码。那么启动类加载器如何找到这些代码呢?
    JDK引入了线程上下文类加载器(TCCL: Thread Context ClassLoader),线程上下文类加载器破坏了“双亲委派模型”,可以在执行线程中抛弃双亲委派加载链,利用线程上下文类加载器去加载所需要的SPI代码。

  • 星归 普通 2022-02-13 6:19 下午

    线程上下文件类加载器 —> 线程上下文类加载器

  • 邹鹏 普通 2021-11-01 1:46 下午

    “它需要调用独立厂商实现部部署在应用程序的 “这句话中’部部署’打错字了,应该是’并部署’