类的生命周期,分为 加载,连接(验证,准备,解析),初始化,使用,卸载 这几个过程。
Class.forName
和 ClassLoader.loadClass
都会执行 加载
过程,将指定的类加载到内存中供使用。
但加载后,在默认情况下: Class.forName
会 初始化
, ClassLoader.loadClass
在加载后什么都不会做。
java.lang.Class
中有两个 forName
方法,参数不同,都是调用了private方法 forName0
:
private static native Class<?> forName0(String name, boolean initialize, ClassLoader loader, Class<?> caller) throws ClassNotFoundException;
返回:使用loader加载的全名为name的类
forName(String className) forName(String name, boolean initialize, ClassLoader loader)
public static Class<?> forName(String className) throws ClassNotFoundException { // 获取调用者的类 Class<?> caller = Reflection.getCallerClass(); // 使用调用者的调用者的ClassLoader加载,加载后对类进行初始化。 return forName0(className, true, ClassLoader.getClassLoader(caller), caller); } 复制代码
public static Class<?> forName(String name, boolean initialize, ClassLoader loader) throws ClassNotFoundException { Class<?> caller = null; SecurityManager sm = System.getSecurityManager(); if (sm != null) { //有SecurityManager时,才需要获取调用者的类。 caller = Reflection.getCallerClass(); if (sun.misc.VM.isSystemDomainLoader(loader)) { ClassLoader ccl = ClassLoader.getClassLoader(caller); if (!sun.misc.VM.isSystemDomainLoader(ccl)) { sm.checkPermission( SecurityConstants.GET_CLASSLOADER_PERMISSION); } } } // 指定类全名,是否初始化,ClassLoader,调用者的类 调用forName0 return forName0(name, initialize, loader, caller); } 复制代码
返回:使用当前ClassLoader加载的全名为name的类
findLoadedClass(name) parent.loadClass(name, false) findBootstrapClassOrNull(name) java.net.URLClassLoader resolve
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // 检查类是否已经加载 Class<?> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { // 双亲委派,优先从parent中执行loadClass,但执行时,不进行连接。 if (parent != null) { c = parent.loadClass(name, false); } else { // name是否在Bootstrap Classloader中加载过,是的话则返回该类。 c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime(); // 执行findClass查找类,findClass由ClassLoader的子类实现。 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; } } 复制代码
ClassLoader中还有一个不带resolve的loadClass方法,在类加载完后不执行连接:
public Class<?> loadClass(String name) throws ClassNotFoundException { return loadClass(name, false); } 复制代码
Class.forName和ClassLoader.loadClass都会执行加载过程。不同的是,在类 加载 后: