V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
Newyorkcity
V2EX  ›  问与答

Java 关于 Class.forName(com.mysql.jdbc.Driver) 未遵守了双亲委派模型这件事有什么比较好资料么?

  •  
  •   Newyorkcity · May 10, 2020 · 1864 views
    This topic created in 2187 days ago, the information mentioned may be changed or developed.
    为什么必须要破坏?

    如何破坏的?

    谢谢
    2 replies    2020-05-11 11:43:26 +08:00
    sawyera
        1
    sawyera  
       May 10, 2020   ❤️ 1
    先说结论:Class.forName 遵循双亲委派机制

    参考:
    Class.forName 方法:
    @CallerSensitive
    public static Class<?> forName(String className)
    throws ClassNotFoundException {
    Class<?> caller = Reflection.getCallerClass();
    return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }

    可以看出是使用 ClassLoader.getClassLoader(caller) 类加载器进行加载的,默认是使用的用户类加载器,还是符合双亲委派机制的。

    如有错误,请指出
    isir1234
        2
    isir1234  
       May 11, 2020   ❤️ 1
    为什么必须要破坏?::
    DriverManager::getConnection 方法需要根据参数传进来的 url 从所有已经加载过的 Drivers 里找到一个合适的 Driver 实现类去连接数据库.
    Driver 实现类在第三方 jar 里, 要用 AppClassLoader 加载. 而 DriverManager 是 rt.jar 里的类, 被 BootstrapClassLoader 加载, DriverManager 没法用 BootstrapClassLoader 去加载 Driver 实现类, 所以只能破坏双亲委派模型, 用它下级的 AppClassLoader 去加载 Driver.

    如何破坏的?::
    > SPI 机制
    Driver 具体的实现类 jar 包在 META-INF/services/java.sql.Driver 文件里写上自己 Driver 实现类的全限定名, 比如 `org.postgresql.Driver` , JDK8 的 DriverManager 在 static 代码块里(JDK14 是在第一次 getConnection 时)会用 ServiceLoader 获取所有的 Driver 并使用 Thread.currentThread().getContextClassLoader() 获取到的 AppClassLoader 加载该类, Driver 实现类的 static 代码块会去调用 DriverManager::registerDriver 将自己注册到 DriverManager 里.

    个人理解...
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   944 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 50ms · UTC 20:07 · PVG 04:07 · LAX 13:07 · JFK 16:07
    ♥ Do have faith in what you're doing.