說明:了解ClassLoader前,先了解 第四章 類加載機制
1、ClassLoader作用
2、類加載器結構
結構:BootstrapClassLoader(祖父)-->ExtClassLoader(爺爺)-->AppClassLoader(也稱為SystemClassLoader)(爸爸)-->自定義類加載器(兒子)
關系:看括號中的排位;彼此相鄰的兩個為父子關系,前為父,後為子
2.1、BootstrapClassLoader
2.2、ExtClassLoader:
2.3、AppClassLoader:
2.4、自定義類加載器:
3、全盤負責機制
概念:假設ClassLoaderA要加載class B,但是B引用了class C,那麼ClassLoaderA先要加載C,再加載B,"全盤"的意思就是,加載B的類加載器A,也會加載B所引用的類
4、雙親委托機制
這也是類加載器加載一個類的整個過程。
過程:假設我現在從類路徑下加載一個類A,
1)那麼app會先查找是否加載過A,若有,直接返回;
2)若沒有,去ext檢查是否加載過A,若有,直接返回;
3)若沒有,去boot檢查是否加載過A,若有,直接返回;
4)若沒有,那就boot加載,若在E:\Java\jdk1.6\jre\lib\*.jar下找到了指定名稱的類,則加載,結束;
5)若沒找到,boot加載失敗;
6)ext開始加載,若在E:\Java\jdk1.6\jre\lib\ext\*.jar下找到了指定名稱的類,則加載,結束;
7)若沒找到,ext加載失敗;
8)app加載,若在類路徑下找到了指定名稱的類,則加載,結束;
9)若沒有找到,拋出異常ClassNotFoundException
注意:
總結:
5、源代碼
1 /** 2 * 根據指定的binary name加載class。 3 * 步驟: 4 * 假設我現在從類路徑下加載一個類A, 5 * 1)那麼app會先查找是否加載過A(findLoadedClass(name)),若有,直接返回; 6 * 2)若沒有,去ext檢查是否加載過A(parent.loadClass(name, false)),若有,直接返回; 7 * findBootstrapClassOrNull(name) 3)4)5)都是這個方法 8 * 3)若沒有,去boot檢查是否加載過A,若有,直接返回; 9 * 4)若沒有,那就boot加載,若在E:\Java\jdk1.6\jre\lib\*.jar下找到了指定名稱的類,則加載,結束; 10 * 5)若沒找到,boot加載失敗; 11 * findClass(name) 6)7)8)9)都是這個方法 12 * 在findClass中調用了defineClass方法,該方法會生成當前類的java.lang.Class對象 13 * 6)ext開始加載,若在E:\Java\jdk1.6\jre\lib\ext\*.jar下找到了指定名稱的類,則加載,結束; 14 * 7)若沒找到,ext加載失敗; 15 * 8)app加載,若在類路徑下找到了指定名稱的類,則加載,結束; 16 * 9)若沒有找到,拋出異常ClassNotFoundException 17 * 注意:在上述過程中的1)2)3)4)6)8)後邊,都要去判斷是否需要進行"解析"過程 18 */ 19 protected synchronized Class<?> loadClass(String name, boolean resolve) 20 throws ClassNotFoundException { 21 Class c = findLoadedClass(name);//檢查要加載的類是不是已經被加載了 22 if (c == null) {//沒有被加載過 23 try { 24 if (parent != null) { 25 //如果父加載器不是boot,遞歸調用loadClass(name, false) 26 c = parent.loadClass(name, false); 27 } else {//父加載器是boot 28 /* 29 * 返回一個由boot加載過的類;3) 30 * 若沒有,就去試著在E:\Java\jdk1.6\jre\lib\*.jar下查找 4) 31 * 若在bootstrap class loader的查找范圍內沒有查找到該類,則返回null 5) 32 */ 33 c = findBootstrapClassOrNull(name); 34 } 35 } catch (ClassNotFoundException e) { 36 //父類加載器無法完成加載請求 37 } 38 if (c == null) { 39 //如果父類加載器未找到,再調用本身(這個本身包括ext和app)的findClass(name)來查找類 40 c = findClass(name); 41 } 42 } 43 if (resolve) { 44 resolveClass(c); 45 } 46 return c; 47 } View Code說明:
附:關於遞歸
遞歸基於棧實現。
上述的代碼如果不清楚遞歸的意義是看不清的。
解釋:
這樣,就完成了雙親委托機制。
遞歸太煩了,實際開發中盡量不要用!