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