java類載入器——ClassLoader

來源:互聯網
上載者:User

標籤:java實現   包名   jsb   http   class類   種類   img   而在   帶來   

Java的設計初衷是主要面向嵌入式領域,對於自己定義的一些類,考慮使用依需求載入原則。即在程式使用到時才載入類,節省記憶體消耗,這時就可以通過類載入器來動態載入。

假設你平時僅僅是做web開發,那應該非常少會跟類載入器打交道,但假設你想深入學習tomcatserver的架構,它是不可缺少的。所謂類載入器。就是用於載入Java類到Java虛擬機器中,它負責讀取Java位元組碼。並轉換成java.lang.Class類的一個執行個體。使位元組代碼.class檔案得以執行。

一般類載入器負責依據一個指定的類找到相應的位元組代碼,然後依據這些代碼定義成一個Java類。另外還負責載入資源。包含影像檔和設定檔。

類載入器在實際使用中給我們帶來的優點是。它能夠使Java類動態地載入到JVM並執行。就可以在程式執行時再載入類,提供了非常靈活的動態載入方式。

比如我們熟悉的Applet,從遠程server下載位元組碼到client動態載入到JVM便能夠執行。

在Java的龐大體系中,能夠將系統分為三種類載入器,各自是:

①   啟動類載入器(Bootstrap ClassLoader):載入對象是Java核心庫。把一些關鍵的Java類載入進JVM,這個載入器使用原生代碼(C/C++)實現的。並非繼承java.lang.ClassLoader,它是全部其它類載入器的終於父載入器,負責載入<JAVA_HOME>/jre/lib檔案夾下且被JVM指定的類庫。事實上它屬於JVM總體的一部分,JVM一啟動就將這些指定的類載入到記憶體中,避免以後過多的I/O操作。提高系統的執行效率。

啟動類載入器無法被Java程式直接使用。

②   擴充類載入器(Extension ClassLoader):載入的對象為Java的擴充庫。即載入<JAVA_HOME>/jre/lib/ext檔案夾裡面的類。

這個類由上面的Bootstrap ClassLoader載入,但因為Bootstrap ClassLoader並不是用Java實現,已經脫離了Java體系,所以假設嘗試調用擴充類載入器的getParent()方法擷取父載入器會得到null,但它的父類載入器是Bootstrap ClassLoader。

Java中能夠直接使用擴充類載入器。

③   應用程式類載入器(Application  ClassLoader):亦叫系統類別載入器(System ClassLoader),它負責載入使用者類路徑(CLASSPATH)指定的類庫。假設程式沒有自訂類載入器。就預設使用應用程式類載入器。它也由Bootstrap ClassLoader載入。但它的父載入類被設定成了Extension ClassLoader。

假設要使用這個載入器,可通過ClassLoader.getSystemClassLoader()擷取。

假如有一天你心血來潮也想自己寫一個類載入器,那麼你僅僅須要繼承java.lang.ClassLoader類就可以。於是能夠用以下的圖2-4-1來清晰表示出各種類載入器的關係,Bootstrap ClassLoader是最根本的類載入器,其不存在父類載入器,Extension ClassLoader由Bootstrap ClassLoader載入。所以它的父類載入器是Bootstrap ClassLoader。Application ClassLoader也是由Bootstrap ClassLoader載入,但它的父載入器被指向了Extension ClassLoader,而其它全部使用者自己定義的類載入器都由Application ClassLoader載入。

由此能夠看出越重要的類載入器就越早被JVM載入,這是考慮到安全性。由於先載入的類載入器會充當下一個類載入器的父載入器,在雙親委派模型機制下,就能確保安全性。

那麼什麼是雙親委派模型?比方爺爺、爸爸、你三代單傳,你們家族都遺傳懶惰基因,每當遇到事情都互相推脫,如今須要一個人去買一包鹽,不然今晚的菜就有色無味了。而你第一個被託付去超市買,但因為你的懶惰。你向你爸爸撒了一頓嬌,你爸爸受不了你僅僅能答應幫你去,在懶惰的驅使下,你爸爸最後找了一個借口說要趕工作。讓你爺爺出去走動走動順便買一包鹽,就這樣你爺爺僅僅能乖乖去超市買鹽。

雙親委派模型就類似這種機制。類載入器載入類時首先託付給父類載入器載入。除非父類載入器不能載入才自己載入。

這樣的模型要求除了頂層的啟動類載入器外,其它的類載入器都要有自己的父類載入器。假如有一個類要載入進來。一個類載入器並不會立即嘗試自己將其載入,而是委派到父類載入器。父類載入器收到後又嘗試委派到其父類載入器,以此類推,直到委派到啟動類載入器,這樣一層一層往上委派。僅僅有當父類載入器反饋自己沒法完畢這個載入時,子載入器才會嘗試自己載入。通過這個機制。保證了Java應用所使用的都是同一個版本號碼的Java核心庫的類。同一時候這個機制也保證了安全性,設想假設Application ClassLoader想要載入一個有破壞性的java.lang.System類,雙親委派模型會一層層向上委派,終於委派給Bootstrap ClassLoader,而Bootstrap ClassLoader檢查到緩衝中已經有了這個類。並不會再載入這個有破壞性的System類。

另外,類載入器還擁有全盤負責機制,即當一個ClassLoader載入一個類時,這個類所依賴的、引用的其它全部類都由這個ClassLoader載入,除非在程式中顯性地指定另外一個ClassLoader載入。

圖2-4-1 類載入器關係

 

在Java中。我們用全然匹配類名來標識一個類。即用包名和類名。而在JVM中。一個類由全然匹配類名和一個類載入器的執行個體ID作為唯一標識。

即是說同一個虛擬機器能夠有兩個包名、類名都相同的類。僅僅要他們由兩個不同類載入器載入。

於是當我們在Java中常常說兩個類相不相等,必須是針對同一個類載入器載入的前提下才有意義。否則就算是相同的位元組代碼,由不同類載入器載入,這兩個類也不是相等的。這樣的特徵為我們提供了隔離機制,在tomcatserver中是十分實用的。

瞭解了JVM的類載入器的各種機制後,看看一個類是如何被類載入器載入進來的。一個類準備載入,類載入器先推斷此類是否已經被載入過(載入過的類會被緩衝在記憶體中),假設緩衝中存在此類則直接返回這個類。

否則擷取父類載入器,假設父類載入器為null,則由Bootstrap ClassLoader載入並返回Class。假設父類載入器不為null,則由父類載入器載入。載入成功就返回Class,載入失敗則依據類路徑尋找class檔案,找到就載入此class並返回Class,找不到就拋出ClassNotFoundException異常。

圖2-4-2 類載入過程

類載入器屬於JVM層級的設計,我們非常多時候基本不會跟他打交道,可是假如你想瞭解整個JAVA體系是怎樣工作的,假如你要設計開發自己的架構或中介軟體或一個較龐大的java軟體。那麼你必須熟悉類載入器的相關機制,在現實的設計中,依據實際情況利用類載入器能夠提供類庫的隔離及共用,保證你的軟體不同層級的邏輯切割程式不會互相影響,提供更好的安全性。



喜歡研究java的同學能夠交個朋友,以下是本人的號:


java類載入器——ClassLoader

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.