Java类加载机制——双亲委派模型

之前也有接触过这方面的知识,但都是看过之后就忘记了,这次做一下学习记录加深自己的对这方面知识的印象。

在java中,通过ClassLoader或者它的子类将字节码文件加载到jvm中,装载过程在此不再说明,本文重点是分析双亲委派模型在源码中的实现。JVM预定义有三种类加载器,当一个 JVM启动的时候,Java缺省开始使用如下三种类加载器:

1)引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader。它负责将/lib下面的核心类库或-Xbootclasspath选项指定的jar包加载到内存中。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作

2)扩展类加载器(extensions class loader):该类加载器在此目录里面查找并加载 Java 类。扩展类加载器是由Sun的                            ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的。它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。它负责将< Java_Runtime_Home >/lib/ext或者由系统变量-Djava.ext.dirs指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器

3)系统类加载器(system class loader):系统类加载器是由 Sun的 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的。它负责将系统类路径java -classpath或-Djava.class.path变量所指的目录下的类库加载到内存中。开发者可以直接使用系统类加载器。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它

下面通过代码分析,代码位于ClassLoader类中:

protected Class loadClass(String name, boolean resolve)
    throws ClassNotFoundException
{
    synchronized (getClassLoadingLock(name)) {
        // 首先检查类是否已经被加载
        Class c = findLoadedClass(name);
        if (c == null) {
            long t0 = System.nanoTime();
            try {
                if (parent != null) {
                    //如果有父加载器,则调用父类方法加载
                    c = parent.loadClass(name, false);
                } else {
                    //如果没有父类加载器,则调用启动类加载类的方法查看类是否被加载,调用本地方法 findBootstrapClass
                    c = findBootstrapClassOrNull(name);
                }
            } catch (ClassNotFoundException e) {
                // ClassNotFoundException thrown if class not found
                // from the non-null parent class loader
            }
            //如果无法从父类加载器或者启动类加载器获取到类的加载信息,则通过调用自定义findClass方法加载类
            if (c == null) {
                // If still not found, then invoke findClass in order
                // to find the class.
                long t1 = System.nanoTime();
                //ClassLoader类中的findClass方法为空实现
                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;
    }
}

不建议重写loadClass()方法,一般重写findClass()方法即可,否则容易破环双亲委派机制。

你可能感兴趣的:(计算机)