JVM組成1 - 類加載器(ClassLoader)

做用

用來動態加載class文件到內存當中java

分類

BootStrapClassLoader:稱爲啓動類加載器,是Java類加載層次中最頂層的類加載器,
負責加載JDK中的核心類庫,如:rt.jar、resources.jar、charsets.jar、sunrsasign.jar、jsse.jar、jce.jar等(加載jdk/jre/lib/下的部分jar包以及jdk/jre/classes下的class文件)
ExtensionClassLoader:稱爲擴展類加載器,負責加載Java的擴展類庫,默認加載jdk/jre/lib/ext/目下的全部jar
AppClassLoader:稱爲系統類加載器,負責加載應用程序classpath目錄下的全部jar和class文件算法

用戶還能夠根據須要定義自已的ClassLoader,自定義的ClassLoader都必須繼承自java.lang.ClassLoader類(包括Java提供Extension ClassLoader和App ClassLoader)api

Bootstrap ClassLoader不繼承ClassLoader,由於它不是一個普通的Java類,底層由C++編寫,已嵌入到了JVM內核當中。當JVM啓動後,Bootstrap ClassLoader也隨着啓動,負責加載完核心類庫後,並構造Extension ClassLoader和App ClassLoader類加載器安全

類加載器原理

ClassLoader使用的是雙親委託模型來搜索類的
每一個ClassLoader實例都有一個父類加載器的引用(不是繼承的關係,是一個包含的關係)。
Bootstrap ClassLoader自己沒有父類加載器,但能夠用做其它ClassLoader實例的父類加載器。
當一個ClassLoader實例須要加載某個類時,它會先把這個任務委託給它的父類加載器,這個過程是由上至下依次檢查的,
首先由最頂層的類加載器Bootstrap ClassLoader試圖加載,
若是沒加載到,則把任務轉交給Extension ClassLoader加載,
若是也沒加載到,則轉交給App ClassLoader 進行加載,
若是它也沒有加載獲得的話,則返回給委託的發起者,由它到指定的文件系統或網絡等URL中加載該類。
若是它們都沒有加載到這個類時,則拋出ClassNotFoundException異常。
不然將這個找到的類生成一個類的定義,並將它加載到內存當中,最後返回這個類在內存中的Class實例對象。網絡

爲何要使用雙親委託這種模型?由於這樣能夠避免重複加載,
當父親已經加載了該類的時候,就沒有必要子ClassLoader再加載一次。
考慮到安全因素,咱們試想一下,若是不使用這種委託模式,那咱們就能夠隨時使用自定義的String來動態替代java核心api中定義的String類型,這樣會存在很是大的安全隱患,
而雙親委託的方式,就能夠避免這種狀況,由於String已經在啓動時就被類加載器(Bootstrcp ClassLoader)加載,因此用戶自定義的ClassLoader永遠也沒法加載一個本身寫的String,
除非你改變JDK中ClassLoader搜索類的默認算法。spa

JVM在搜索類的時候,如何斷定兩個class是相同?
JVM在斷定兩個class是否相同時,不只要判斷兩個類名是否相同,並且要判斷是否由同一個類加載器加載的。
只有二者同時知足的狀況下,JVM才認爲這兩個class是相同的。
就算兩個class是同一份class字節碼,若是被兩個不一樣的ClassLoader實例所加載,JVM也會認爲它們是兩個不一樣class。對象

自定義類加載器

1.繼承java.lang.ClassLoader
2.重寫父類的findClass方法繼承

由於JDK已經在loadClass方法中幫咱們實現了ClassLoader搜索類的算法,
當在loadClass方法中搜索不到類時,loadClass方法就會調用findClass方法來搜索類,因此咱們只需重寫該方法便可。
如沒有特殊的要求,通常不建議重寫loadClass搜索類的算法。內存

相關文章
相關標籤/搜索