類載入子系統Class Loader
Java架構圖:
2.1 類載入器的作用
- 類載入器負責從檔案系統或網路中載入Class檔案,class檔案在檔案開頭有特定的檔案標識。
- ClassLoader只負責class檔案載入,至於它是否可以執行,則由執行引擎(Execution Engine)決定。
- 載入的類資訊放在一塊稱之為方法區的空間。除了類的資訊外,方法區中還會存放執行時常量池資訊等。
2.2 類載入器ClassLoader角色
3. 類的載入過程階段一:Loading載入階段
載入:
- 透過一個類的許可權定名獲取定義此類的二進位制位元組流。
- 將這個位元組流所代表的的靜態儲存結構轉化為方法區執行時資料結構。
- 在記憶體中生成一個代表這個類的java.lang.Class物件,作為方法區這個類的各個資料訪問入口。
4. 類的載入過程階段二:Verification驗證階段
- 驗證的目的在於確保Class檔案的位元組流中所包含的資訊符合當前虛擬機器的要求,保證被載入類的正確性,不會危害虛擬機器的自身安全等。
- 主要包含四種驗證:檔案格式驗證(class檔案魔術0xcafebabe)、後設資料驗證、位元組碼驗證、符號引用驗證。
5. 類的載入過程階段三:Preparation準備階段
- 為類變數分配記憶體並且設定該類變數的初始值,即零值。
- 這裡不包含final關鍵字修飾的static,因為final在編譯時就會分配了。
- 這裡不會為例項變數分配初始化,類變數會分配在方法區,而例項變數是隨著物件一起分配到Java堆中
6. 類的載入過程階段四:Resolution解析階段
- 將常量池的符號引用轉化為直接引用的過程。
- 解析動作主要包括類、介面、欄位、類方法、介面方法、方法型別等。
5. 類的載入過程階段五:Initialization初始化階段
- 初始化階段就是執行類構造方法
()的過程。 - 此方法不需要定義,是javac編譯器自動收集類中的所有類變數的賦值動作和靜態程式碼塊中的語句合併起來。
- 構造方法中指令按語句在原始檔中出現的順序執行。
()不同於類的構造器。 - 若該類具有父類,JVM會保證子類的
()執行前,父類的 ()已經執行完畢。 - 虛擬機器必須保證一個類的
()方法在多執行緒下被同步加鎖。
6. 類載入器的分類
- JVM支援兩種型別的類載入器,分別是引導類載入器Bootstrap ClassLoader和自定義類載入器User-Defined ClassLoader
- 從概念上講,自定義類載入器一般指的是程式中由開發人員自定義的一類類載入器,但是Java虛擬機器卻沒有這樣定義,而是將所有原生於抽象類ClassLoader*的類載入器都劃分為自定義載入器。
public class HelloLoader {
public static void main(String[] args) {
// 獲取系統類類載入器
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
System.out.println(classLoader);//jdk.internal.loader.ClassLoaders$AppClassLoader@36baf30c
// 獲取其上層,擴充套件類載入器
ClassLoader parentClassLoader = classLoader.getParent();
System.out.println(parentClassLoader);//jdk.internal.loader.ClassLoaders$PlatformClassLoader@b4c966a
// 獲取其上層引導類載入器
ClassLoader bootstrapClassLoader = parentClassLoader.getParent();
System.out.println(bootstrapClassLoader);//null
//對於使用者自定義類載入器:使用系統類載入器進行載入
//注意!Java核心類庫使用的是引導類載入器
ClassLoader helloLoader = HelloLoader.class.getClassLoader();
System.out.println(helloLoader);//jdk.internal.loader.ClassLoaders$AppClassLoader@36baf30c
}
}
虛擬機器自帶的載入器:
- 啟動類載入器(引導類載入器Bootstrap ClassLoader)
- 這個類載入器使用C/C++語言實現的,巢狀在JVM內部。
- 它主要用來載入Java的核心類庫(JAVA_HOME/jre/lib/rt.jar、resources.jar、sun.boot.class路徑下的內容),用於提供JVM自身需要的類
- 並不繼承java.lang.ClassLoader,沒有父類載入器
- 載入擴充套件類和應用程式類載入器,並制定為他們的父類載入器。
- 出於安全的考慮,Bootstrap啟動類載入器只載入包含包名為java、javax、sun等開頭的類
- 擴充套件類載入器(Extension ClassLoader)
- Java語言編寫,由sun.misc.Launcher$ExtClassLoader實現。
- 派生於ClassLoader類
- 父類載入器是啟動類載入器
- 應用程式類載入器(系統類載入器AppClassLoader)
- java語言編寫,由sun.misc.Launcher$AppClassLoader實現
- 派生於ClassLoader
- 父類載入器為擴充套件類載入器
- 它負責載入環境變數classpath或系統屬性等
- 該類是程式中預設的類載入器,一般來說,Java應用程式的類都是由它來完成載入。
- 透過ClassLoader$getSystemClassLoader()方法可以獲取到該類載入器