理論瞭解:html
關於類加載器的雙親委託機制基本上都據說過,面試時可能偶爾也會被問到,可是可能都是網上去找了一個理論性的答案臨時瞭解了一下,並未對它究竟是個什麼樣的機制有深刻的瞭解,因此接下來準備深刻了解它,在瞭解以前固然得有理論作爲支撐。java
在以前【http://www.cnblogs.com/webor2006/p/8905978.html】已經對類加載器的一個層次關係有了一個大致的瞭解,回顧一下:web
在父親委託機制中,各個加載器按照父子關係造成了樹形結構【注意:並不是物理上的樹形結構,而是邏輯上的樹形結構】,附了根類加載器以外,其他的類加載器都有且只有一個父加載器。下面來看另一張圖:面試
其中loader1和loader2是自定義類加載器,所謂的類加載器的雙親委託機制是這樣:假如說想要經過loader1來加載本身所編寫的Sample類,而類加載器雙親委託機制並非直接由loader1直接來加載Sample類,而是先轉交給loader1的父親系統類加載器來完成,而系統類加載器又會轉交給擴展類加載器去完成, 而因爲擴展類加載器還有父親根類加載器,因此說又會轉到根類加載器去加載,因爲它木有父加載器了,此時根類加載器就開始嘗試去加載Sample類了,可是!此時根類加載器是沒法加載Sample類的,爲何?緣由以下:ide
也就是說此時根類加載器會加載失敗,可是並非失敗了就立馬就返回了,而是把加載的任務又返回給它的下一級子類,也就是擴展類加載器,而擴展類加載器也加載不了自定義的類,緣由跟根類加載器相似,以下:spa
也就是不進行相應路徑的配置其擴展類加載器加載Sample類確定也失敗了,因而繼續傳給它的下一級子類系統類加載器(也叫應用加載器),而它加載的規則以下:3d
也就是通常狀況下系統類加載會成功的加載我們定義的Sample類了,經過這麼一個從底部往上和從頂部往下的過程其實最終加載Sample類是由系統類加載器完成的,而非是load1完成,不過會將結果返回給load1,以上的整個過程則爲雙親委託機制(也叫父親委託機制),大致能夠概括爲:某一個類加載器想要加載一個類,它並不是立馬本身去加載該類,而是委託給它的父親去加載,若是父親還有父親則繼續委託,直到根類加載器了沒父親了則由它去加載,若是加載不成功則會從上到下進行委託加載,整個鏈上只要有一個加載器能加載成功,則最終的加載結果就是成功的,最終流程就會返回到第一次想加載類的類加載器。htm
【注意】:上面的加載機制只是在標準的hospot虛擬機上是這樣的,固然JDK裏採用的也是標準的這種方式,可是不併代碼其它的JVM都是採用的這種雙親委託機制,瞭解一下。對象
再來看一下該圖:blog
這個順序恰好就是我們以前所描述的。下面再針對不一樣的加載類具體描述一下其加載的特性:
另外還需瞭解一個概念,僅瞭解既可:若是有一個類加載器可以成功加載Test類,那麼這個類加載器被稱爲定義類加載器,全部能成功返回Class對象引用的類加載器(包括定義類加載器)都被稱爲初始類加載器。具體理解以下:
實驗:
既然已經對類加載器的雙親委託機制有了必定的瞭解,下面編寫代碼來使用一下類加載器:
在加載自定義類以前,我們先來加載系統的類,以下:
在運行以前,先來看一下getClassLoader()這個方法的說明:
編譯運行:
這也是根類加載器的職責所在,再來回顧下:
好,那接下來再來加載我們本身定義的類C,以下:
而AppClassLoader的職責以下:
那我們來看一下AppClassLoader類:
位置Launcher類中,而這個類是ide根據class文件反編譯出來的,由於它並非開源的,以下:
其中瞭解一下它的類繼承關係: