類的加載流程包含:加載、驗證、準備、解析、初始化java
做爲第一個階段,虛擬機須要完成了之後三個步驟緩存
確保被加載類的正確性,包含檢測如下信息安全
爲類的靜態變量分配內存,並將其初始化默認值bash
將類中的符號引用轉換爲直接引用網絡
解析階段就是虛擬機將常量池內符號引用替換爲直接引用,解析的動做主要是針對類的接口、字段、類方法、接口方法、方法類型、方法句柄和調用點限定符7類符號引用進行。數據結構
爲類的靜態變量賦予正確的初始值,到了初始階段,纔開始真正執行類中定義的Java程序代碼。jvm
示例圖佈局
==注意:這裏父類加載器並非經過繼承關係來實現的,而是採用組合實現的==加密
在java虛擬機的角度來講只存在兩種不一樣的類加載器spa
在開發者的角度來講,類的加載器能夠大體劃分爲三類
類加載的方式
雙親委派機制的流程:若是一個類加載器收到了一個類加載的請求,首先他不會嘗試本身加載該類,而是把這個請求委託給父類加載器加載該類,依次向上傳遞,所以,全部的類記載請求都會請求到啓動類加載器中,父類加載器在他的搜索範圍內沒有找到所須要的類時,即沒法完成該類的加載,子加載器纔會嘗試本身去加載該類,若是尚未找到,那麼直接拋出異常
示例流程詳解
雙親委派機制的意義
代碼示例
// 首先判斷該類型是否已經被加載
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
//若是沒有被加載,就委託給父類加載或者委派給啓動類加載器加載
if (parent != null) {
//若是存在父類加載器,就委派給父類加載器加載
c = parent.loadClass(name, false);
} else {
//若是不存在父類加載器,就檢查是不是由啓動類加載器加載的類,經過調用本地方法native Class findBootstrapClass(String name)
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
複製代碼
一般狀況下,咱們都是直接使用系統類加載器。可是,有的時候,咱們也須要自定義類加載器。好比應用是經過網絡來傳輸 Java類的字節碼,爲保證安全性,這些字節碼通過了加密處理,這時系統類加載器就沒法對其進行加載,這樣則須要自定義類加載器來實現。自定義類加載器通常都是繼承自 ClassLoader類,從上面對 loadClass方法來分析來看,咱們只須要重寫 findClass 方法便可。
自定義類加載器的核心在於對字節碼文件的獲取,若是是加密的字節碼則須要在該類中對文件進行解密