java收录jvm

JVM学习(二)续1-ClassLoader代码解读-双亲委派模

2018-08-02  本文已影响2人  J先生有点儿屁

1. ClassLoader的继承关系

ClassLoader是什么鬼?为什么我们要如此大费周章的讲解这个?
还记得AppClassLoader、ExtClassLoader么?他们与ClassLoader之间的关系是什么?


ClassLoader继承关系 AppClassLoader+ExtClassLoader
URLClassLoader
SecureClassLoader
ClassLoader

2. ClassLoader重要方法loadclass()代码解读。

直接上代码,代码上注释有说明。

```
public Class<?> loadClass(String name) throws ClassNotFoundException {
    return loadClass(name, false);
}

protected Class<?> loadClass(String name, boolean resolve) //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 {
                    // 如果父类不存在,则交给BootstrapClassLoader来加载。 什么时候父类不存在呢?其实就是ExtClassLoader不存在父类的情况。
                    c = findBootstrapClassOrNull(name);
                }
            } catch (ClassNotFoundException e) {
                // ClassNotFoundException thrown if class not found
                // from the non-null parent class loader
                // 如果父类通过缓存+加载都无法找到,并抛出ClassNotFoundException异常时,则捕获异常但不处理。
            }

            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;
    }
}
```

代码中有几个关键调用需要注意:

Class<?> c = findLoadedClass(name)通过缓存查找判断是否存在该类。
  进一步查看该方法实现,又调用了native findLoadedClass0方法。
    ```
    protected final Class<?> findLoadedClass(String name) {
        if (!checkName(name))
            return null;
        return findLoadedClass0(name);
    }

    private native final Class<?> findLoadedClass0(String name);
    ```
② 当parent != null时,c = parent.loadClass(name, false);。如果父类不为空,则委派给父类的loadClass()方法执行。
当 parent == null是,```c = findBootstrapClassOrNull(name);```父类如果为空时,则委派给BootstrapClassLoader来查找。

这里就是双亲委派模型出现了。

③ 当在经过父类们缓存查找和加载后,仍然未找到该类,则本加载器会亲自进行查找c = findClass(name);。这个方法很关键。
    ```
    protected Class<?> findClass(String name) throws ClassNotFoundException {
            throw new ClassNotFoundException(name);
        }
    ```

3. 双亲委派模型的验证

    public static void main(String[] args) {
        ClassLoader loader = TestStatic3.class.getClassLoader();
        System.out.println(loader);
        System.out.println(loader.getParent());
        System.out.println(loader.getParent().getParent());
    }

输出结果:

sun.misc.Launcher$AppClassLoader@b4aac2
sun.misc.Launcher$ExtClassLoader@193b845
null

4. 双亲委派模型的优点

这里补充下几个双亲委派模型的特点。

上一篇 下一篇

猜你喜欢

热点阅读