1. JVM类加载机制
JVM的ClassLoader通过Parent属性定义父子关系,可以形成树状结构。其中引导类、扩展类、系统类三个加载器是JVM内置的
它们的作用分别是:
BootstrapClassLoader引导类加载器:---加载/jdk1.7.0_67/jre/目录下的核心库
ExtClassLoader拓展类加载器:---加载/jdk1.7.0_67/jre/lib/ext/目录下的扩展包
AppClassLoader系统类加载器:---加载CLASSPATH路径下的包
可用以下代码验证:
import java.net.URL; import java.net.URLClassLoader; /* 分析BootstrapClassLoader/ExtClassLoader/AppClassLoader的加载路径 * */ public class ClassPath_of_Bootstrap_Ext_AppClassLoader { public static void main(String[] args) { System.out.println("BootstrapClassLoader 的加载路径: "); URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs(); for(URL url : urls) System.out.println(url); System.out.println("----------------------------"); //取得扩展类加载器 URLClassLoader extClassLoader = (URLClassLoader)ClassLoader.getSystemClassLoader().getParent(); System.out.println(extClassLoader); System.out.println("扩展类加载器 的加载路径: "); urls = extClassLoader.getURLs(); for(URL url : urls) System.out.println(url); System.out.println("----------------------------"); //取得应用(系统)类加载器 URLClassLoader appClassLoader = (URLClassLoader)ClassLoader.getSystemClassLoader(); System.out.println(appClassLoader); System.out.println("应用(系统)类加载器 的加载路径: "); urls = appClassLoader.getURLs(); for(URL url : urls) System.out.println(url); System.out.println("----------------------------"); } }
BootstrapClassLoader 的加载路径: file:/D:/app/Java/jdk1.7.0_67/jre/lib/resources.jar file:/D:/app/Java/jdk1.7.0_67/jre/lib/rt.jar file:/D:/app/Java/jdk1.7.0_67/jre/lib/sunrsasign.jar file:/D:/app/Java/jdk1.7.0_67/jre/lib/jsse.jar file:/D:/app/Java/jdk1.7.0_67/jre/lib/jce.jar file:/D:/app/Java/jdk1.7.0_67/jre/lib/charsets.jar file:/D:/app/Java/jdk1.7.0_67/jre/lib/jfr.jar file:/D:/app/Java/jdk1.7.0_67/jre/classes ---------------------------- sun.misc.Launcher$ExtClassLoader@d9660d 扩展类加载器 的加载路径: file:/D:/app/Java/jdk1.7.0_67/jre/lib/ext/access-bridge.jar file:/D:/app/Java/jdk1.7.0_67/jre/lib/ext/dnsns.jar file:/D:/app/Java/jdk1.7.0_67/jre/lib/ext/jaccess.jar file:/D:/app/Java/jdk1.7.0_67/jre/lib/ext/localedata.jar file:/D:/app/Java/jdk1.7.0_67/jre/lib/ext/sunec.jar file:/D:/app/Java/jdk1.7.0_67/jre/lib/ext/sunjce_provider.jar file:/D:/app/Java/jdk1.7.0_67/jre/lib/ext/sunmscapi.jar file:/D:/app/Java/jdk1.7.0_67/jre/lib/ext/sunpkcs11.jar file:/D:/app/Java/jdk1.7.0_67/jre/lib/ext/zipfs.jar ---------------------------- sun.misc.Launcher$AppClassLoader@18f1d7e 应用(系统)类加载器 的加载路径: file:/D:/workspace/myTestProject/build/classes/ ----------------------------
2. 父委托机制或者说双亲委派模型
JDK API中指出:
protected Class<?> loadClass(String name,boolean resolve) throws ClassNotFoundException使用指定的 二进制名称来加载类。此方法的默认实现将按以下顺序搜索类:
调用 findLoadedClass(String)
来检查是否已经加载类。
在父类加载器上调用 loadClass
方法。如果父类加载器为null,则使用虚拟机的内置类(称为“bootstrap class loader”)加载器。
调用 findClass(String)
方法查找类。
图例1—父委托机制
图例2—双亲委派模型
public synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { Class clazz = null; // (0) Check our previously loaded local class cache clazz = findLoadedClass0(name); if (clazz != null) { if (log.isDebugEnabled()) log.debug(" Returning class from cache"); if (resolve) resolveClass(clazz); return (clazz); } // (0.1) Check our previously loaded class cache clazz = findLoadedClass(name); if (clazz != null) { if (log.isDebugEnabled()) log.debug(" Returning class from cache"); if (resolve) resolveClass(clazz); return (clazz); } // (0.2) Try loading the class with the system class loader, to prevent // the webapp from overriding J2SE classes try { clazz = system.loadClass(name); if (clazz != null) { if (resolve) resolveClass(clazz); return (clazz); } } catch (ClassNotFoundException e) { // Ignore } boolean delegateLoad = delegate || filter(name); // (1) Delegate to our parent if requested if (delegateLoad) { if (log.isDebugEnabled()) log.debug(" Delegating to parent classloader1 " + parent); ClassLoader loader = parent; if (loader == null) loader = system; try { clazz = loader.loadClass(name); if (clazz != null) { if (log.isDebugEnabled()) log.debug(" Loading class from parent"); if (resolve) resolveClass(clazz); return (clazz); } } catch (ClassNotFoundException e) { ; } } // (2) Search local repositories if (log.isDebugEnabled()) log.debug(" Searching local repositories"); try { clazz = findClass(name); if (clazz != null) { if (log.isDebugEnabled()) log.debug(" Loading class from local repository"); if (resolve) resolveClass(clazz); return (clazz); } } catch (ClassNotFoundException e) { ; } // (3) Delegate to parent unconditionally if (!delegateLoad) { if (log.isDebugEnabled()) log.debug(" Delegating to parent classloader at end: " + parent); ClassLoader loader = parent; if (loader == null) loader = system; try { clazz = loader.loadClass(name); if (clazz != null) { if (log.isDebugEnabled()) log.debug(" Loading class from parent"); if (resolve) resolveClass(clazz); return (clazz); } } catch (ClassNotFoundException e) { ; } } throw new ClassNotFoundException(name); }