在java中,ClassLoader負責把一個java類加載進Java虛擬機。爲了防止重複加載和安全性方便的考慮,ClassLoader是具備層次結構的。java
ClassLoader的主要方法包括:git
protected final Class<?> defineClass(String name, byte[] b, int off, int len) throws ClassFormatError { return defineClass(name, b, off, len, null); }
經過defineClass是將byte數組轉換爲JVM可以識別的對象,能夠看出,字節數組能夠來自本地,網絡等途徑web
protected final Class<?> findLoadedClass(String name) { if (!checkName(name)) return null; return findLoadedClass0(name); }
經過類的全名來加載一個類數組
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // 首先檢查class是否已經加載 Class c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // 當父classLoader沒有加載的成功的時候拋出異常 } if (c == null) { // 若是還還加載成功,試圖調用findClass來加載類 long t1 = System.nanoTime(); c = findClass(name); // 記錄狀態 sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }
能夠看出,加載類的時候都是先從父類中加載安全
protected Class<?> findClass(String name) throws ClassNotFoundException { throw new ClassNotFoundException(name); }
findClass默認是沒有任何實現的,只是拋出異常,所以咱們能夠覆蓋該方法, 重寫咱們本身的類加載途徑java-web
代碼例子:怎麼使用classLoader加載自定義byte數組並經過反射調用其中方法網絡
https://git.oschina.net/null_584_3382/java-web-example/tree/masterspa
從文章前面的描述中,能夠看出 class loader在加載類的時候,優先是從其父加載器中加載,而且每一個Class Loader 都有一個字段指向其父加載器(若是沒有指定默認爲AppClassLoader).net
ClassLoader的層次結構:code
上面的圖是隨便找的,下面簡單介紹一下
這個類是爲JVM本身服務的,加載JVM自身工做所須要的類,這個類徹底是由JVM本身控制的。該類其實並不遵照前面所規定的等級加載制度。這個類即沒有父加載器,也沒有子加載器。
這個加載器主要用於加載 java.ext.dirs目錄下的類,也算是一種特殊的類加載器,他是往上能追溯到的最高加載器
這個類就是專門爲咱們使用的,他的父加載器ExtClassLoader ,全部在ClassPath下的類都由他加載(前提你沒有定義其餘本身的ClassLoader)。咱們本身實現的ClassLoader的父加載器就是這個類。
ExtClassLoader 和AppClassLoader都是Launch的內部類,都繼承URLClassLoader,而URLClassLoader又繼承ClassLoader。
第一種方式是隱式加載方式,加載一個類的時候,若是他的父類沒有加載,就會先加載其父類(順帶說一句,本身實現ClassLoader 的時候,也要準守先從父加載器中加載,否則加載到Java.xxx 的類的時候,就會提示報錯,由於 java.xxx 的類是不容許從其餘地方加載的)
第二種方式是顯示加載,也就是咱們本身顯示使用loadClass方法加載
// TODO