ExclassLoader java
AppClassLoaderapi
上图类关系出自sun.misc.Launcher类,能够看出ExclassLoader与 AppClassLoader都继承与URLClassLoader,而非继承Bootstrap ClassLoaderapp
public class MyAppClassLoader { private static class Test { Test() { System.out.println("Hello World!"); } } Launcher launcher = new Launcher(); public static void main(String[] args) throws ClassNotFoundException { ClassLoader classLoader = MyAppClassLoader.class.getClassLoader(); System.out.println(classLoader); System.out.println(classLoader.getParent()); System.out.println(classLoader.getParent().getParent()); } }
"C:\Program Files\Java\jdk1.7.0_80\bin\java" "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=61577:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_80\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\rt.jar;D:\ideaprojects\NewCoderTest\out\production\NewCoderTest" MyAppClassLoader sun.misc.Launcher$AppClassLoader@7b7035c6 sun.misc.Launcher$ExtClassLoader@3da997a null Process finished with exit code 0
ExclassLoader与 AppClassLoader都继承与URLClassLoade,而URLClassLoade实现抽象类ClassLoader。ide
分析Launcher源码oop
Launcher.classthis
public Launcher() { Launcher.ExtClassLoader var1; try {
//先建立ExtClassLoader var1 = Launcher.ExtClassLoader.getExtClassLoader(); } catch (IOException var10) { throw new InternalError("Could not create extension class loader"); } try {
//由ExtClassLoader再去建立它的子类加载器,再讲将该类加载器置为Launcher的默认类加载器 this.loader = Launcher.AppClassLoader.getAppClassLoader(var1); } catch (IOException var9) { throw new InternalError("Could not create application class loader"); } Thread.currentThread().setContextClassLoader(this.loader); String var2 = System.getProperty("java.security.manager"); if(var2 != null) { SecurityManager var3 = null; if(!"".equals(var2) && !"default".equals(var2)) { try { var3 = (SecurityManager)this.loader.loadClass(var2).newInstance(); } catch (IllegalAccessException var5) { ; } catch (InstantiationException var6) { ; } catch (ClassNotFoundException var7) { ; } catch (ClassCastException var8) { ; } } else { var3 = new SecurityManager(); } if(var3 == null) { throw new InternalError("Could not create SecurityManager: " + var2); } System.setSecurityManager(var3); } }
ClassLoader.classidea
private static synchronized void initSystemClassLoader() { if (!sclSet) { if (scl != null) throw new IllegalStateException("recursive invocation"); sun.misc.Launcher l = sun.misc.Launcher.getLauncher(); if (l != null) { Throwable oops = null; scl = l.getClassLoader(); try { scl = AccessController.doPrivileged( new SystemClassLoaderAction(scl)); } catch (PrivilegedActionException pae) { oops = pae.getCause(); if (oops instanceof InvocationTargetException) { oops = oops.getCause(); } } if (oops != null) { if (oops instanceof Error) { throw (Error) oops; } else { // wrap the exception throw new Error(oops); } } } sclSet = true; } }
追踪到最后由该类进行调用 (看注释能够得出,做为默认加载器被调用)
@CallerSensitive
public static ClassLoader getSystemClassLoader() {
initSystemClassLoader();
if (scl == null) {
return null;
}
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkClassLoaderPermission(scl, Reflection.getCallerClass());
}
return scl;
}
看ClassLoader.class中的loadClass方法,探究类加载原理spa
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
//getClassLoadingLock方法,经过类名获取 synchronized (getClassLoadingLock(name)) { // 检查该类是否已经被加载过 Class c = findLoadedClass(name); if (c == null) {
//计时,输出纳秒级别时间 long t0 = System.nanoTime(); try {
//因而可知BootstrapClassLoader并非ExtClassLoader加载器的父加载器,仅仅只是在经过父加载优先行不通的状况下,才会去找BootstrapClassLoader if (parent != null) {
//先查找父类加载器,false表示 c = parent.loadClass(name, false); } else {
//查找BootstrapClass,找不到返回null 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();
//若是都没找到经过本加载器加载 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; } }
private final ConcurrentHashMap<String, Object> parallelLockMap; 经过类名,若是paralleLockMap这个ConcurrentHashMap为空,这返回ClassLoader,不然经过putIfAbsent源码能够看到,该方法若是一个HashEntry中可以找到该key对应value值则返回该value, 若是找不到,则返回null,则返回Object protected Object getClassLoadingLock(String className) { Object lock = this; if (parallelLockMap != null) { Object newLock = new Object(); //经过putIfAbsent源码能够看到,该方法若是一个HashEntry中可以找到该key对应value值则返回该value,若是不能找到,则返回null,下面会分析ConcurrentHashMap中的该源码 lock = parallelLockMap.putIfAbsent(className, newLock); if (lock == null) { lock = newLock; } } return lock; }
protected final Class<?> findLoadedClass(String name) {
if (!checkName(name))
return null;
return findLoadedClass0(name);
}
//native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其余语言(如C和C++)实现的文件中。
private native final Class findLoadedClass0(String name);
总结:由上的代码分析能够分析出loadClass加载类的过程,以及对BootstrapClassLoader的误解。3d