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;
网友评论