JVM(四)JVM的双亲委派模型

一、两种不一样的类加载器

  从JAVA虚拟机的角度来说,只存在两种不一样的类加载器:一种是启动类加载器(Bootstrap ClassLoader),这个类加载器使用C++语言实现,是虚拟机自身的一部分;另外一种就是全部其余的类加载器,这些加载器都由Java语言实现,独立于虚拟机外部,而且全都继承自抽象类java,lang.ClassLoader。java

二、类加载器双亲委派模型图

  

三、对4个加载器的理解

  (1)启动类加载器:这个类加载器负责将存放在<JAVA_HOME>\lib 目录下的,例如rt.jar包。this

  (2)扩展类加载器:这个类加载器由sun.misc.Launcher$ExtClassLoader实现。它负责加载<JAVA_HOME>\lib\ext 目录下的。或者被java.ext.dirs系统变量所指定的路径中的全部类库,开发者可用直接使用扩展类加载器。spa

  (3)应用程序类加载器:这个类加载器由sun.misc.Launcher$AppClassLoader实现。因为这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,全部通常也称它为系统类加载器。它负责加载用户路径(ClassPath)上所指定的类库,开发者可用直接使用这个类加载器,若是应用程序中没有自定义过本身的类加载器,通常状况下这个就是程序中默认的类加载器。code

  (4)自定义类加载器:就是本身自定义的类加载器。blog

四、双亲委派模型的实现

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
                    // 若是父类加载器抛出ClassNotFoundException 
                    // from the non-null parent class loader
                    // 说明父类加载器没法完成加载请求
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    // 在父类加载器没法加载的时候,再调用自己的findClass方法进行类加载 
                    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;
        }
    }   

  注意:即便自定义了本身的类加载器,强行用defineClass()方法区加载一个以"java.lang"开头的类也不会成功,若是尝试这样的话,将会收到一个由虚拟机本身抛出的"java.lang.ScurityException:Prohibitted package name:java.lang"异常。继承

相关文章
相关标签/搜索