JVM系列-類載入機制
簡介
在java中,類的宣告週期總共分為以下幾種: 載入(Loading),驗證(Verification),準備(Preparation),解析(Analysis),
初始化(Initialization),使用(Using),解除安裝(Unloading)。其中,驗證,準備,解析統稱為連線(Linking)如圖
一、載入:
在載入階段,JVM需要完成以下準備:
通過一個類的全限定名來獲取定義此類的二進位制位元組流(並非要從class檔案獲取,也可從jar或war中讀取,也可以在執行時動態生成,還可以編譯jsp時獲取)
二、驗證:
驗證是為了確保class檔案中的位元組流包含的資訊符合JVM的要求,並且不會危害JVM自身的安全,驗證大致分為四中方法:
- 檔案格式驗證: 驗證位元組流是否符合class檔案的規範,例:主次版本號是否在當前JVM範圍內,常量池中的常量是否有不被支援的型別
- 元資料驗證: 對位元組碼描述的資訊進行語義分析(javac編譯階段的語義分析),以保證其描述資訊符合java語言規範要求
- 位元組碼驗證: 通過資料流和控制流分析,確保程式是合法的,符合邏輯的
- 符號引用驗證: 確保解析動作能正確執行
PS: 驗證階段是很重要的,但不是必須的,如果所引用的類已經經過了反覆校驗,可以使用 -Xverifynone引數來關閉一些驗證措施,
用來縮短JVM載入時間
三、準備:
準備階段是正式為類變數分配記憶體並設定類變數初始值的階段,這些變數所使用的記憶體都將在方法區中進行分配。
這裡進行的記憶體分配僅包含類變數(被static修飾的變數),不包含例項變數(區別見末尾)。
初始值例: public static int value = 123;
如上宣告的話value的值會在準備階段後為0而不是123。因為此時尚未執行任何java方法,value被賦值123是程式被編譯後存放於
類構造器<client>中。但是還有一種特殊情況:
初始值例:public static final int value = 123;
這時在準備階段後會為value生成ConstantValue屬性,賦值為123而非0。
類變數(靜態變數):
- 在類中被static修飾,並且必須在構造方法和語句塊之外
- 無論一個類建立了多少變數,類只擁有類變數的一份拷貝
- 類變數在程式開始是建立,程式結束時銷燬
- 靜態變數儲存在靜態儲存區,經常被宣告為常量
- 靜態變數可以通過className,VariableName訪問到
例項變數:
- 宣告在類中,不在方法,構造方法,語句塊之內
- 當一個物件被例項化之後,每個例項變數的值就跟著確定
- 例項變數在物件建立是建立,物件銷燬時銷燬
- 例項變數的值應至少被一個方法,構造方法或語句塊引用,使得外部可以用這些方法獲取例項變數的值
- 例項變數可以直接通過變數名訪問,但在靜態方法和其它類中,應使用完全限定名:ObjectReference.VariableName
未完待續