ClassLoader细节杂谈

100 阅读1分钟

URLClassLoader

对于AppClassLoader和ExtClassLoader而言,这两个类是继承了URLClassLoader这个类,而URLClassLoader这个类是继承了SecureClassLoader,之后这个SecureClassLoader是继承了ClassLoader这个抽象类
AppClassLoader和ExtClassLoader继承URLClassLoader有一个重要的一环,是在URLClassLoader中重写了findClass这个方法,使得这两个类在进行本类进行加载的过程中可以执行类的加载过程。而SecureClassLoaders是用于安全校验的,对于用户来说用处不大。这个URLClassLoader主要是用来协助实际的类加载器完成加载,因为补充了findClass,完善了类的实际加载过程。

public Class<?> loadClass(String name, boolean resolve)
    throws ClassNotFoundException
{
    int i = name.lastIndexOf('.');
    if (i != -1) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPackageAccess(name.substring(0, i));
        }
    }

    if (ucp.knownToNotExist(name)) {
        // The class of the given name is not found in the parent
        // class loader as well as its local URLClassPath.
        // Check if this class has already been defined dynamically;
        // if so, return the loaded class; otherwise, skip the parent
        // delegation and findClass.
        Class<?> c = findLoadedClass(name);
        if (c != null) {
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
        throw newClassNotFoundException(name);
    }

    return (super.loadClass(name, resolve));
}

上面的是AppClassLoader关于loadClass的重写,发现其实,并没干什么,还是用的classLoader类的loadClass方法进行加载。

主动使用和被动使用

Class.forName()

调用的方法是会使类进行加载链接初始化全过程的。可以通过类的具体描述可以看出来,同时可以进去看源码

public static Class<?> forName(String className)
            throws ClassNotFoundException {
    Class<?> caller = Reflection.getCallerClass();
    return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}

会发现,initialize这个参数是true的。

classLoader.loadClass

classLoader.loadClass方法是不负责类的初始化的,甚至都不会进行解析,可以看以下源码

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

可以看出,resolve这个字段被赋值为false。