双亲委派模式

一、双亲委派模式

   首先先了解类加载器,类加载器通过类的全限定名称加载到JVM中形成Class对象(二进制字节码)。

  JVM提供了三种类加载器,启动类加载器(Bootstrap),拓展类加载器(Extension),应用类加载器(Application)。

二、类加载器

  启动类加载器

      启动类加载器主要是加载JVM自身需要的类。这个类的实现是通过C++来实现类的加载的,主要是加载<JAVA_HONE>/lib/下的核心类库或者是-Xbootclasspath参数指定路径下的jar包到内存中。

 拓展类加载器

     拓展类加载器主要是负责加载<JAVA_HONE>/lib/ext/目录下的jar包或者是系统变量-Djava.ext.dir指定位路径中的类库。

 应用类加载器

    应用类加载器主要负责加载系统类路径java -classpath或者-D java.class.path指定路径下的类库。

   需要注意的是在类加载的过程中是通过这三种加载器和自定义加载器其相互配合加载的。java虚拟机对class的加载是按照需要加载的。当应用成旭需要去使用这个类时,才会去执行加载类到内存中。而加载类的的模式是双亲委派模式。

三、双亲委派模式

    工作原理:

     双亲委派模式除了启动类加载器外,其他加载器都需要有自己的父类加载器。也就是当一个类加载器收到一个类加载请求时,不会先去自己加载,而是把这个请求委托给自己的父类加载器去加载,请求会最终将达到顶层的启动类加载器。当父类加载器无法加载时,子类加载器会去执行加载。盗图如下:

代码实现:

  ClassLoader类是加载类的父类

 1.loadClass加载类的方法

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.findLoadedClass(name)会先查找缓存,如果缓存命中会直接返回。

 2.判断是否有父类加载器,有执行loadClass()。没有则是启动加载器,执行启动加载器加载类。

 3.如果都没有找到,执行findClass()方法去加载。

类于类加载器的关系

  在JVM中标识两个Class对象是否为同一个类对象的必要条件是:

 类的限定名称必须完全相同,加载这个类的ClassLoader(指ClassLoader实例对象)必须相同。

猜你喜欢

转载自blog.csdn.net/qq_28126793/article/details/82222099