類加載器分類
- JVM支持兩種類型的類加載器,分別爲
引導類加載器
( Bootstrap ClassLoader它不是java語言編寫)和自定義類加載器
(User- Defined ClassLoader) - 從概念上來講,自定義類加載器一般指的是程序中由開發人員自定義的一類類加載器,但是Java虛擬機規範卻沒有這麼定義,而是
將所有派生於抽象類ClassLoader的類加載器都劃分爲自定義類加載器
- 無論類加載器的類型如何劃分,
在程序中我們最常見的類加載器始終只有3個
,如下所示:
ExtClassLoader和AppClassLoader簡介繼承了ClassLoader,所以他們也可以理解爲一種自定義類加載器。
獲取類加載器
虛擬機自帶的加載器
啓動類加載器(引導類加載器,Bootstrap Clas sLoader)
- 這個類加載使用
C/C++語言實現
的,並不繼承java體系機構的java. lang. ClassLoader,沒有父加載器
,嵌自在JVM內部。這個類加載器我們是獲取不到的 - 它
用來加載Java的核心庫
(JAVA HOME/j re/lib/rt. jar、resources. j ar或sun. boot . class . path路徑下的內容) ,用於提供JVM自身需要的類 加載擴展類和應用程序類加載器
,並指定爲他們的父類加載器。- 出於安全考慮,
Bootstrap啓動類加載器只加載包名爲java、javax、sun等開頭的類
擴展類加載器( Extension ClassLoader)
Java語言編寫
,由sun . misc . LauncherSExtClassLoader實現。派生於ClassLoader類
父類加載器爲啓動類加載器
- 從
java. ext.dirs系統屬性所指定的目錄中加載類庫
,或從JDK的安裝目錄的jre/lib/ext子目錄
(擴展目錄)下加載類庫。如果用戶創建的JAR放在此目錄下,也會自動由擴展類加載器加載。
應用程序類加載器(系統類加載器,AppClassLoader)
- jaya語言編寫,由sun . mi sc . LauncherSAppClassLoader實現
- 派生於ClassLoader類
- 父類加載器爲擴展類加載器
- 它負責加載環境變量classpath或系統屬性java.class.path 指定路徑下的類庫
該類加載是程序中默認的類加載器
,一般來說,Java應用的類 都是由它來完成加載- 通過ClassLoader#getSystemClassLoader ()方法可以獲取到該類加載器
用戶自定義類加載器
在Java的日 常應用程序開發中,類的加載幾乎是由上述3種類加載器相互配合執行的,在必要時,我們還可以自定義類加載器,來定製類的加載方式。
- 爲什麼要自定義類加載器?
隔離加載類、修改類加載的方式、擴展加載源、防止源碼泄漏
用戶自定義類加載器實現步驟:
- 開發人員可以通過
繼承抽象類java. lang. ClassLoader類的方式
, 實現自己的類加載器,以滿足一些特殊的需求 - 在JDK1.2之前, 在自定義類加載器時,總會去繼承ClassLoader類並重寫loadClass()方法,從而實現自定義的類加載類,但是在
JDK1.2之後
已不再建議用戶去覆蓋loadClass()方法,而是建議把自定義的類加載邏輯寫在findClass()方法中
- 在編寫自定義類加載器時,如果沒有太過於複雜的需求,
可以直接繼承URLClassLoader類
,這樣就可以避免自己去編寫findClass()方法
及其獲取字節碼流的方式
,使自定義類加載器編寫更加簡潔。
看個例子:
補充內容
在JVM中表示兩個class對象是否爲同一個類存在兩個必要條件
➢類的完整類名必須一致,包括包名。
➢加載這個類的ClassLoader (指ClassLoader實例對象)必須相同。
換句話說,在JVM中,即使這兩個類利象(class對象)來源同一個Class文件,被同一個虛擬機所加載,但只要加載它們的ClassLoader實例對象不同
,那麼這兩個類對象也是不相等
的。
對類加載器的引用
JVM必須知道一個類型是由啓動加載器加載的還是由用戶類加載器加載的。如果一個類型是由用戶類加載器加載的,那麼JVM會將這個類加載器的一一個引用作爲類型信息的一部分保存在方法區中。
當解析一個類型到另一個類型的引用的時候,JVM需要保證這兩個類型的類加載器是相同
的。
類的主動使用和被動使用
Java程序對類的使用方式分爲:主動使用和被動使用。區別在於會不會導致類的初始化。
- 主動使用,又分爲七種情況:
1.創建類的實例
2.訪問某個類或接口的靜態變量,或者對該靜態變量賦值
3.調用類的靜態方法
4.反射(比如: Class. forName (“com. huijie. Test”) )
5.初始化一個類的子類
6.Java虛擬機啓動時被標明爲啓動類的類
7.JDK 7開始提供的動態語言支持: .
java. lang. invoke . MethodHandle實例的解析結果
REF_ getStatic、 REF_ putStatic、REF_ invokeStatic句柄對
應的類沒有初始化,則初始化
- 除了以上七種情況,其他使用Java類的方式都被看作是對類的被動使用,
都不會導致類的初始化
。