jvm學習筆記:類載入過程
類載入器子系統
類載入器的作用是載入class檔案到記憶體
載入階段->連結階段->初始化階段
-
ClassLoader只負責class檔案的載入,至於是否能夠執行由執行引擎判斷
-
載入的類資訊存放在方法區的一個區域,該區域稱為常量池,還存放了字串字面量、數字常量等
類載入過程
判斷類是否載入,已經載入了就開始連結
載入階段
過程
(1)通過全限類名找到類.class檔案,獲取檔案的位元組流
(2)將位元組流按照靜態類的資料格式轉換成儲存在方法區的執行時資料結構
(3)為該類生成唯一的java.lang.Class的物件,並在堆中分配記憶體,作為方法呼叫和屬性的介面
找到.class檔案->獲取位元組流->轉換成執行時資料結構->記憶體中生成Class物件
class檔案的不同載入方式
(1)從本地檔案系統載入
(2)網路載入
(3)壓縮包載入,比如jar包、war包
(4)執行時計算生成,動態代理模式下常用
(5)其他檔案生成,比如jsp檔案
(6)資料庫提取
(7)加密檔案中獲取,比如防反編譯的class檔案
連結過程
驗證(Verify)(檢查位元組碼檔案規範)
驗證位元組流是否符合java虛擬機器規範,符合規範就繼續連結過程,否則丟擲異常
準備(prepare(初始化類變數:分配記憶體、賦初值為0|null)
為類變數分配記憶體空間,並賦初值0值(null值)
注意:準備過程只為靜態變數賦初值,不會為常量賦初值,因為常量在編譯階段就已經完成了賦值
解析(Resolve)(解析引用)
將符號引用解析成直接引用
符號引用: 用符號來描述引用的目標
直接引用: 直接指向目標的指標、偏移量
初始化過程
初始化
執行構造器方法 cinit
構造器方法
javac編譯時會將類的靜態變數賦值語句、靜態程式碼塊合併成一個構造器方法
(1)構造器方法的指令執行順序與java程式碼的語句順序一致
(2)JVM會保證父類的構造器方法在子類構造器方法之前完成執行
(3)構造器方法只執行靜態程式碼塊語句和類變數的賦值,如果原始碼中無這兩者就不會生成構造器方法
(4)JVM會為構造器方法加執行緒同步鎖,保證每個類只加載一次
例子
private static int num = 1;
static{
num = 2;
number = 20;
}
private static int number=10;
上述特殊情況:number的宣告在符值後面,但是jvm依然能初始化,因為在構造器方法之前已經完成了連結階段的prepare過程,該過程為number符值了0
過程: linking.prepare:number=0->init:number=20, number=10
init階段的符值是嚴格按照程式碼順序的