JVM在運行時會產生三個ClassLoader
Bootstrap ClassLoader
Extension ClassLoader和AppClassLoader
其中
Bootstrap是用C++編寫的
我們在Java中看不到它
是null
它用來加載核心類庫
在JVM源代碼中這樣寫道
static const char classpathFormat[] =
%/lib/rt
jar:
%/lib/i
n
jar:
%/lib/sunrsasign
jar:
%/lib/jsse
jar:
%/lib/jce
jar:
%/lib/charsets
jar:
%/classes
;
知道為什麼不需要在classpath中加載這些類了吧?人家在JVM啟動的時候就自動加載了
並且在運行過程中根本不能修改Bootstrap加載路徑
Extension ClassLoader用來加載擴展類
即/lib/ext中的類
最後AppClassLoader才是加載Classpath的
ClassLoader加載類用的是委托模型
即先讓Parent類(而不是Super
不是繼承關系)尋找
Parent找不到才自己找
看來ClassLoader還是蠻孝順的
三者的關系為:AppClassLoader的Parent是ExtClassLoader
而ExtClassLoader的Parent為Bootstrap ClassLoader
加載一個類時
首先BootStrap先進行尋找
找不到再由ExtClassLoader尋找
最後才是AppClassLoader
為什麼要設計的這麼復雜呢?其中一個重要原因就是安全性
比如在Applet中
如果編寫了一個java
lang
String類並具有破壞性
假如不采用這種委托機制
就會將這個具有破壞性的String加載到了用戶機器上
導致破壞用戶安全
但采用這種委托機制則不會出現這種情況
因為要加載java
lang
String類時
系統最終會由Bootstrap進行加載
這個具有破壞性的String永遠沒有機會加載
我們來看這段代碼
[code]//A
java
public class A{
public static void main(String[] args){
A a=new A();
System
out
println(System
getProperty(
java
ext
dirs
));
System
out
println(a
getClass()
getClassLoader());
B b=new B();
b
print();
}
}
//B
java
public class B{
public void print(){
System
out
println(this
getClass()
getClassLoader());
}
}[/code]
我們將它放在Classpath中
則打印出
sun
misc
Launcher$AppClassLoader@
e
c
sun
misc
Launcher$AppClassLoader@
e
c
可見都是由AppClassLoader來加載的
我們將其放在%jre%/lib/ext/classes(即ExtClassLoader的加載目錄
其加載/lib/ext中的jar文件或者子目錄classes中的class文件)中
則會打印出
sun
misc
Launcher$ExtClassLoader
sun
misc
Launcher$ExtClassLoader
我們將A
class放到%jre%/lib/ext/classes中
而將B
class放到classpaht中又會怎麼樣呢?結果是
sun
misc
Launcher$ExtClassLoader
Exception in thread
main
java
lang
NoClassDefFoundError:B
at A
main(A
java:
)
怎麼會這樣呢?這其中有一個重要的問題
A類當然是由ExtClassLoader來加載的
B類要由哪個加載呢?B類要由調用它自己的類的類加載器(真拗口)
也就是說
A調用了B
所以B由A的類加載器ExtClassLoader來加載
ExtClassLoader根據委托機制
先拜托Bootstrap加載
Bootstrap沒有找到
然後它再自己尋找B類
還是沒找到
所以拋出異常
ExtClassLoader不會請求AppClassLoader來加載!你可能會想
這算什麼問題
我把兩個類放到一起不就行了?
呵呵
沒這麼簡單
比如JDBC是核心類庫
而各個數據庫的JDBC驅動則是擴展類庫或在classpath中定義的
所以JDBC由Bootstrap ClassLoader加載
而驅動要由AppClassLoader加載
等等
問題來了
Bootstrap不會請求AppClassLoader加載類啊
那麼
他們怎麼實現的呢?我就涉及到一個Context ClassLoader的問題
調用Thread
getContextClassLoader
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19529.html