Java中一共有四個類加載器,之因此叫類加載器,是程序要用到某個類的時候,要用類加載器載入內存。
這四個類加載器分別爲:Bootstrap ClassLoader、Extension ClassLoader、AppClassLoader
和URLClassLoader,他們的做用其實從名字就能夠大概推測出來了。其中AppClassLoader在不少地方被叫作System ClassLoader
Bootstrap ClassLoader是在JVM開始運行的時候加載java的核心類,是用C++編寫的,它用來加載核心類庫,在JVM源代碼中這樣寫道:
static const char classpathFormat[] =
"%/lib/rt.jar:"
"%/lib/i18n.jar:"
"%/lib/sunrsasign.jar:"
"%/lib/jsse.jar:"
"%/lib/jce.jar:"
"%/lib/charsets.jar:"
"%/classes";
Extension ClassLoader是用來加載擴展類,即/lib/ext中的類。
AppClassLoader用來加載Classpath的類,是和咱們關係最密切的類。
URLClassLoader用來加載網絡上遠程的類,暫且不討論。
它們之間的關係:
1.Parent-Child,按順序從大到小。不是簡單的繼承關係。
2.ClassLoader有個getParent的方法,可是Ext ClassLoader調用後獲得的是null,bootstrap是JVM本身的,用戶看不到。
3.classloader的委託機制:當等級比較低的ClassLoader要加載某個類的時候,它首先會請求Parent加載器來加載,Parent再請求它的Parent
好比如今Ext要加載了,它往上請求。若是最大的Bootstrap找不到,那麼Boot會叫Ext本身找找,Ext找不到,是不會讓下一級的App去找的,此時就報出ClassNotFoundException
4. 類A調用類B,B會要求調用它的類的類加載器來加載它,也就是B會要求加載A的加載器來加載B。這就會有個問題,若是他們在一塊兒,那不要緊,確定某個 classloader會把它們倆都加載好。可是若是A在/lib/ext文件夾中,而B在Classpath中呢?過程是這樣的首先加載A,那麼一層層 上到Bootstrap Classloader,boot沒找到因此ext本身找,找到了,沒問題;加載B,由於A調用了B,因此也從bootstrap來找,沒找到,而後A的 ext classloader來找仍是沒找到,可是不再會往下調用了,因而報出ClassNotFoundException。
可是現實生活 中有不少應用,好比JDBC核心方法在覈心庫而驅動在擴展庫,是一定在兩個地方的,那怎麼辦呢?要用到Context ClassLoader咱們在創建一個線程Thread的時候,能夠爲這個線程經過setContextClassLoader方法來指定一個合適的 classloader做爲這個線程的context classloader,當此線程運行的時候,咱們能夠經過getContextClassLoader方法來得到此context classloader,就能夠用它來載入咱們所須要的Class。默認的是system classloader。利用這個特性,咱們能夠「打破」classloader委託機制了,父classloader能夠得到當前線程的context classloader,而這個context classloader能夠是它的子classloader或者其餘的classloader,那麼父classloader就能夠從其得到所需的 Class,這就打破了只能向父classloader請求的限制了。這個機制能夠知足當咱們的classpath是在運行時才肯定,並由定製的 classloader加載的時候,由system classloader(即在jvm classpath中)加載的class能夠經過context classloader得到定製的classloader並加載入特定的class(一般是抽象類和接口,定製的classloader中是其實現),例 如web應用中的servlet就是用這種機制加載的.java
http://hi.baidu.com/qmiao128/item/c983bffca5ca6fec1b111f26web