关于SPI打破双亲委派机制的一点见解

关于SPI打破双亲委派机制的一点见解

  • 先说结论
    • 什么是双亲委派机制(parents deletation model)
    • 什么是SPI
    • Java中关键的类加载器
    • 为什么说打破双亲委派又使用双亲委派呢

先说结论

个人理解,“SPI打破双亲委派”的说法并不是说完全突破双亲委派直接加载,而是指在本应由父加载器加载的位置委托子加载器去加载,实际上最后还是会走双亲委派的流程。

什么是双亲委派机制(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.demo.Test)在其所负责的域里搜寻此类字节码,如果找到,则加载之;如果找不到,则表示无法加载,把代理权限往下(父->子)转移,直到某个加载器在负责的加载域中找到该类为止。
举个例子,孙子要买玩具,会先问爸爸有没有买过这个玩具,爸爸会问爷爷有没有买过,如果买过,那下一辈就不需要再买了。但是不同年龄层次的人了解的玩具肯定是不同的,如果爷爷没见过这种玩具,就会去让爸爸买,爸爸也没见过就会去让孙子买,大概就是这个意思吧。
关于SPI打破双亲委派机制的一点见解_第1张图片
父加载器与子加载器的关系并不是继承关系,而是组合关系!
父加载器与子加载器的关系并不是继承关系,而是组合关系!
父加载器与子加载器的关系并不是继承关系,而是组合关系!
重要的事情说三遍。

什么是SPI

SPI全称Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用框架扩展和替换组件。
举个例子,JDBC中,jdk只定义了Driver这个驱动类接口,而具体的实现由厂商自己开发。这里不是我们讨论的重点,可以从这篇文章中窥得一二
传送门
关于SPI打破双亲委派机制的一点见解_第2张图片

Java中关键的类加载器

与之前图相对应,Java中中比较核心的类加载器分别为

sun.misc.Launcher.ExtClassLoader
sun.misc.Launcher.AppClassLoader

这两个加载器都继承自URLClassLoader,再往上继承自SecureClassLoader,顶级抽象类便是ClassLoader。想要了解的同学可以去翻一下源码。

在Launcher类的构造器中,会将ExtClassLoader设置为AppClassLoader的父加载器。

public Launcher() {
   
        Launcher.ExtClassLoader var1;
        try {
   
            var1 = Launcher.ExtClassLoader.getExtClassLoader();
        } catch (IOException var10) {
   
            throw new InternalError("Could not create extension class loader", var10);
        }

        try {
   
            this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
        } catch (IOException var9) {
   
            throw new InternalError("Could not create application class loader", var9);
        }

        Thread.currentThread().

你可能感兴趣的:(Java学习中的一点见解,java,jvm)