JVM的類加載機制全面解析(轉)

什么是類加載機制

JVM把描述類的數據從Class文件加載到內存,并對數據進行校驗、轉換解析和初始化,最終形成可以被JVM直接使用的Java類型,這就是JVM的類加載機制。

如果你對Class文件的結構還不熟悉,可以參考之前的文章Class文件結構全面解析(上)Class文件結構全面解析(下)

類的生命周期

類從被加載到內存中,到被卸載出內存,一共分為以下幾步:

加載(Loading)

驗證(Verification)

準備(Preparation)

解析(Resolution)

初始化(Initialization)

使用(Using)

卸載(Unloading)

類加載的全過程,包括其中的加載驗證準備解析初始化幾個階段。

加載

加載是類加載的第一階段,在這一步中JVM規范要求完成了以下三件事:

通過一個類的全限定名來獲取定義這個類的二進制字節流。

將這個字節流多代表的靜態存儲結構轉化為方法區的運行時數據結構。

在內存中生成一個代表這個類的java.lang.Class對象。

以上要求其實并不具體,JVM的具體實現和應用都是比較靈活的。比如:獲取這個類的二進制字節流,并沒有說從哪獲取,怎么獲取,于是就有了從壓縮包中讀取(jar、war、ear)、從網絡中獲取(Applet)、運行時計算生成(動態代理)。對于不是數組的類的加載,我們可以定義自己的類加載器去控制字節流的獲取方式。但是,對于數組類就不一樣了,因為數組類本身不是通過類加載器創建的,而是JVM直接創建的。

驗證

這一階段是為了保證Class文件的字節流中包含的信息符合當前JVM的要求,并且不危害JVM自身的安全。大致分為以下四個階段:

文件格式驗證

驗證字節流是否符合Class文件格式的規范,能不能被當前JVM處理。驗證點比較多,比如:是否以魔數0xCAFEBABE開頭、主次版本號是否在當前JVM的處理范圍內、常量池的常量是否有不被支持的常量類型、CONSTANT_Utf8_info類型的常量中是否有不符合UTF8編碼的數據等等。這個階段是基于二進制字節流進行驗證的,只有這個階段驗證通過了,字節流才能進入內存的方法區儲存。

元數據驗證

這個階段主要是對類的元數據信息進行語義分析和校驗,保證不存在不符合Java語言規范的元數據信息。比如:除了java.lang.Object以外的類是否有父類、是否繼承了一個不允許被繼承的類、非抽象類是否實現了其父類或接口中要求實現的所有方法、是否覆蓋了父類的final字段等等。

字節碼校驗

這個階段通過數據流和控制流分析,確保程序語義是合法的、符合邏輯的。比如:放置和使用操作棧時數據類型保證一致、保證跳轉指令不會跳轉到方法體以外的字節碼指令上、保證方法體中的類型轉換是有效的等等。

符號引用校驗

這個階段是對類自身以外(常量池中的各種符號引用)的信息進行匹配性校驗,它發生在解析步驟中,確保解析能正常執行,比如:符號引用中通過字符串描述的全限定名是否能找到對應的類、符號引用中的類字段方法的訪問性是否可以訪問當前類等等。

準備

在這個階段里,為靜態變量分配內存并設置靜態變量初始值。這里說的初始值通常情況下,不是代碼中寫的初始值,而是數據類型的零值。代碼中寫的初始值,是在初始化階段賦值的。如果是靜態常量(被final修飾),這個階段就會被直接賦值為代碼中寫的初始值。

解析

在這個階段里,JVM把常量池內的符號引用替換為直接引用。符號引用以一組符號來描述所引用的目標,符號可以是任何形式的字面量,只要使用時能無歧義地定位到目標即可,它和JVM實現的內存布局無關。直接引用可以是直接指向目標的指針、相對偏移量或是一個能間接定位到目標的句柄,它是和JVM實現的內存布局相關的。如果有了直接引用,那么引用的目標肯定在內存中存在。

解析主要針對類或接口、字段、類方法、接口方法、方法類型、方法句柄和調用點限定符的符號引用進行,分別對應常量池的CONSTANT_Class_info、CONSTANT_Fieldref_info、CONSTANT_Methodref_info、CONSTANT_InterfaceMethodref_info、CONSTANT_MethodType_info、CONSTANT_MethodHandle_info和CONSTANT_InvokeDynamic_info。

初始化

初始化階段才真正開始執行類中定義的字節碼,也是執行類構造器()方法的過程。()方法是由編譯器自動收集類中的所有靜態變量的賦值動作和靜態語句塊中的語句合并產生的,編譯器收集的順序是用語句在源文件中出現的順序所決定的,靜態語句塊只能訪問到定義在靜態語句塊之前的變量,定義在它之后的變量,靜態語句塊可以賦值,但是不能訪問。

JVM會保證在子類的()方法執行之前,父類的()方法已經執行完畢,也就是說父類中定義的靜態語句塊要優先于子類的變量賦值操作。如果類沒有靜態語句塊,也沒有對靜態變量賦值,編譯器就不會為這個類生成()方法。接口的()方法不需要先執行父接口的()方法,只有當父接口中定義的變量使用時,父接口才會被初始化。

JVM會保證一個類的()方法在多線程環境中被正確地加鎖、同步。如果一個線程在執行這個類的()方法,其他線程都需要阻塞等待,當()方法執行完后,其他線程也不會再次進入()方法。同一個類加載器下,一個類只會被初始化一次。

結語

這次我們了解了類加載過程的幾個階段,分別是加載驗證準備解析初始化加載是把二進制字節碼載入內存,驗證是校驗字節流中包含的信息是否符合當要求,準備是為靜態變量分配內存并設置靜態變量初始值,解析是把常量池內的符號引用替換為直接引用,初始化是執行所有靜態變量的賦值動作和靜態語句塊中的語句。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,497評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,727評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,193評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,411評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,945評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,777評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,978評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,216評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,657評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,960評論 2 373

推薦閱讀更多精彩內容