美文网首页
类加载的双亲委派机制

类加载的双亲委派机制

作者: 啊啊啊哼哼哼 | 来源:发表于2020-05-19 11:38 被阅读0次

    类加载的过程:

    加载,链接(验证,准备,解析),初始化
    loadClass只做到了加载。

    Java中的类加载器包括四类:

    • BootstrapClassLoader:加载java包路径下的核心类库;
    • ExtClassLoader:加载ext路径下的类;
    • AppClassLoader:加载程序所在目录下的类;
    • 自定义ClassLoader: 自定义加载路径。

    双亲委派的工作流程:

    一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,自底向上的递归查询父加载器是否已经加载了这个类,如果BootstrapClassLoader返回未加载这个类,载自顶向下的尝试加载这个类。
    双亲委派机制保证了一个类只被加载一次,并且在程序的各种类加载器环境中都能保证是同一个类。


    双亲委派.png

    双亲委派的实现:

    protected Class<?> loadClass(String name, boolean resolve)
            throws ClassNotFoundException
        {
            synchronized (getClassLoadingLock(name)) {
                // First, check if the class has already been loaded
                Class<?> c = findLoadedClass(name);
                if (c == null) {
                    long t0 = System.nanoTime();
                    try {
                        if (parent != null) {
                            c = parent.loadClass(name, false);
                        } else {
                            c = findBootstrapClassOrNull(name);
                        }
                    } catch (ClassNotFoundException e) {
                        // ClassNotFoundException thrown if class not found
                        // from the non-null parent class loader
                    }
    
                    if (c == null) {
                        // If still not found, then invoke findClass in order
                        // to find the class.
                        long t1 = System.nanoTime();
                        c = findClass(name);
    
                        // this is the defining class loader; record the stats
                        sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                        sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                        sun.misc.PerfCounter.getFindClasses().increment();
                    }
                }
                if (resolve) {
                    resolveClass(c);
                }
                return c;
            }
        }
    

    破坏双亲委派模型的场景

    • 双亲委派模型是1.2引入的,类加载是1.0引入的
    • SPI(Service Provider Interface)机制(JDBC等等)
      用JDBC连接的例子来说明,下面调用getConnection方法来获得连接,我们需要调用getConnection方法来加载MySQL的jar包,但是我们实际获得的初始化的类加载器是当前类的类加载器,也就是DriverManager的类加载器,DriverManager在 package java.sql; 下,因为我们获得的类加载器是BootstrapClassLoader,导致无法加载MySQL的jar包。Java引入了一个Thread.contextClassLoader,可以任意设置当前线程的ClassLoader来解决这个问题。
    DriverManager.getConnection("jdbc://mysql://localhost:3306");
    

    相关文章

      网友评论

          本文标题:类加载的双亲委派机制

          本文链接:https://www.haomeiwen.com/subject/qsgvohtx.html