类加载ClassLoader.loadClass()与Class.forName()的区别

1. 类加载说明

在Java中,类装载器把一个类装入Java虚拟机中,要经过三个步骤来完成:加载、链接和初始化,其中链接又可以分成校验、准备和解析三步

除了解析外,其它步骤是严格按照顺序完成的,各个步骤的主要工作如下:

  • 加载:查找和导入类或接口的二进制数据;
  • 链接:又可以分成校验、准备和解析三步,其中解析步骤是可以选择的;
    • 校验:检查导入类或接口的二进制数据的正确性;
    • 准备:给类的静态变量分配并初始化存储空间;
    • 解析:将符号引用转成直接引用;
  • 初始化:激活类的静态变量的初始化Java代码和静态Java代码块。

2. 源码

// ClassLoader.Java
    public Class loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
    }

    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 (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

    /**
     * Links the specified class.  执行链接
     */
    protected final void resolveClass(Class c) {
        resolveClass0(c);
    }
    // native方法
    private native void resolveClass0(Class c);
  • 从以上ClassLoader.loadClass()的源码来看, 由于并不会执行resolveClass(Class c)链接, 因此也不会执行加载的第三步骤初始化.
  • Class.forName()是会执行初始化.
//CLass.java
    @CallerSensitive
    public static Class forName(String className)
                throws ClassNotFoundException {
        Class caller = Reflection.getCallerClass();
        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }

    /** Called after security check for system loader access checks have been made. */
    private static native Class forName0(String name, boolean initialize,
                                            ClassLoader loader,
                                            Class caller)
        throws ClassNotFoundException;

你可能感兴趣的:(类加载ClassLoader.loadClass()与Class.forName()的区别)