JVM的類加載機制全面解析

什么是類加載機制

JVM把描述類的數(shù)據(jù)從Class文件加載到內(nèi)存迫悠,并對數(shù)據(jù)進行校驗、轉(zhuǎn)換解析和初始化,最終形成可以被JVM直接使用的Java類型贾惦,這就是JVM的類加載機制。

類的生命周期

類從被加載到內(nèi)存中午乓,到被卸載出內(nèi)存,一共分為以下幾步:

  • 加載(Loading)
  • 驗證(Verification)
  • 準備(Preparation)
  • 解析(Resolution)
  • 初始化(Initialization)
  • 使用(Using)
  • 卸載(Unloading)
    類加載的全過程,包括其中的加載惧磺、驗證、準備捻撑、解析磨隘、初始化幾個階段。

加載

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

通過一個類的全限定名來獲取定義這個類的二進制字節(jié)流番捂。
將這個字節(jié)流多代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運行時數(shù)據(jù)結(jié)構(gòu)。
在內(nèi)存中生成一個代表這個類的java.lang.Class對象描验。
以上要求其實并不具體白嘁,JVM的具體實現(xiàn)和應(yīng)用都是比較靈活的。比如:獲取這個類的二進制字節(jié)流膘流,并沒有說從哪獲取絮缅,怎么獲取,于是就有了從壓縮包中讀群艄伞(jar耕魄、war、ear)彭谁、從網(wǎng)絡(luò)中獲任(Applet)、運行時計算生成(動態(tài)代理)缠局。對于不是數(shù)組的類的加載则奥,我們可以定義自己的類加載器去控制字節(jié)流的獲取方式。但是狭园,對于數(shù)組類就不一樣了读处,因為數(shù)組類本身不是通過類加載器創(chuàng)建的,而是JVM直接創(chuàng)建的唱矛。

驗證

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

文件格式驗證

驗證字節(jié)流是否符合Class文件格式的規(guī)范绎谦,能不能被當前JVM處理管闷。驗證點比較多,比如:是否以魔數(shù)0xCAFEBABE開頭窃肠、主次版本號是否在當前JVM的處理范圍內(nèi)包个、常量池的常量是否有不被支持的常量類型、CONSTANT_Utf8_info類型的常量中是否有不符合UTF8編碼的數(shù)據(jù)等等冤留。這個階段是基于二進制字節(jié)流進行驗證的赃蛛,只有這個階段驗證通過了恃锉,字節(jié)流才能進入內(nèi)存的方法區(qū)儲存。

元數(shù)據(jù)驗證

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

字節(jié)碼校驗

這個階段通過數(shù)據(jù)流和控制流分析谜洽,確保程序語義是合法的萝映、符合邏輯的。比如:放置和使用操作棧時數(shù)據(jù)類型保證一致阐虚、保證跳轉(zhuǎn)指令不會跳轉(zhuǎn)到方法體以外的字節(jié)碼指令上序臂、保證方法體中的類型轉(zhuǎn)換是有效的等等。

符號引用校驗

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

準備

在這個階段里,為靜態(tài)變量分配內(nèi)存并設(shè)置靜態(tài)變量初始值避矢。這里說的初始值通常情況下悼瘾,不是代碼中寫的初始值,而是數(shù)據(jù)類型的零值审胸。代碼中寫的初始值亥宿,是在初始化階段賦值的。如果是靜態(tài)常量(被final修飾)砂沛,這個階段就會被直接賦值為代碼中寫的初始值烫扼。

解析

在這個階段里,JVM把常量池內(nèi)的符號引用替換為直接引用尺上。符號引用以一組符號來描述所引用的目標材蛛,符號可以是任何形式的字面量圆到,只要使用時能無歧義地定位到目標即可怎抛,它和JVM實現(xiàn)的內(nèi)存布局無關(guān)。直接引用可以是直接指向目標的指針芽淡、相對偏移量或是一個能間接定位到目標的句柄马绝,它是和JVM實現(xiàn)的內(nèi)存布局相關(guān)的。如果有了直接引用挣菲,那么引用的目標肯定在內(nèi)存中存在富稻。

解析主要針對類或接口掷邦、字段、類方法椭赋、接口方法抚岗、方法類型、方法句柄和調(diào)用點限定符的符號引用進行哪怔,分別對應(yīng)常量池的CONSTANT_Class_info宣蔚、CONSTANT_Fieldref_info、CONSTANT_Methodref_info认境、CONSTANT_InterfaceMethodref_info胚委、CONSTANT_MethodType_info、CONSTANT_MethodHandle_info和CONSTANT_InvokeDynamic_info叉信。

初始化

初始化階段才真正開始執(zhí)行類中定義的字節(jié)碼亩冬,也是執(zhí)行類構(gòu)造器()方法的過程。()方法是由編譯器自動收集類中的所有靜態(tài)變量的賦值動作和靜態(tài)語句塊中的語句合并產(chǎn)生的硼身,編譯器收集的順序是用語句在源文件中出現(xiàn)的順序所決定的硅急,靜態(tài)語句塊只能訪問到定義在靜態(tài)語句塊之前的變量,定義在它之后的變量鸠姨,靜態(tài)語句塊可以賦值铜秆,但是不能訪問。

JVM會保證在子類的()方法執(zhí)行之前讶迁,父類的()方法已經(jīng)執(zhí)行完畢连茧,也就是說父類中定義的靜態(tài)語句塊要優(yōu)先于子類的變量賦值操作。如果類沒有靜態(tài)語句塊巍糯,也沒有對靜態(tài)變量賦值啸驯,編譯器就不會為這個類生成()方法。接口的()方法不需要先執(zhí)行父接口的()方法祟峦,只有當父接口中定義的變量使用時罚斗,父接口才會被初始化。

JVM會保證一個類的()方法在多線程環(huán)境中被正確地加鎖宅楞、同步针姿。如果一個線程在執(zhí)行這個類的()方法,其他線程都需要阻塞等待厌衙,當()方法執(zhí)行完后距淫,其他線程也不會再次進入()方法。同一個類加載器下婶希,一個類只會被初始化一次榕暇。

結(jié)語

這次我們了解了類加載過程的幾個階段,分別是加載、驗證彤枢、準備狰晚、解析和初始化。加載是把二進制字節(jié)碼載入內(nèi)存缴啡,驗證是校驗字節(jié)流中包含的信息是否符合當要求壁晒,準備是為靜態(tài)變量分配內(nèi)存并設(shè)置靜態(tài)變量初始值,解析是把常量池內(nèi)的符號引用替換為直接引用业栅,初始化是執(zhí)行所有靜態(tài)變量的賦值動作和靜態(tài)語句塊中的語句讨衣。

打個廣告,本人博客地址是:風吟個人博客

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末式镐,一起剝皮案震驚了整個濱河市反镇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌娘汞,老刑警劉巖歹茶,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異你弦,居然都是意外死亡惊豺,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門禽作,熙熙樓的掌柜王于貴愁眉苦臉地迎上來尸昧,“玉大人,你說我怎么就攤上這事旷偿∨胨祝” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵萍程,是天一觀的道長幢妄。 經(jīng)常有香客問我,道長茫负,這世上最難降的妖魔是什么蕉鸳? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮忍法,結(jié)果婚禮上潮尝,老公的妹妹穿的比我還像新娘。我一直安慰自己饿序,他們只是感情好勉失,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著嗤堰,像睡著了一般戴质。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上踢匣,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天告匠,我揣著相機與錄音,去河邊找鬼离唬。 笑死后专,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的输莺。 我是一名探鬼主播戚哎,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼嫂用!你這毒婦竟也來了型凳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤嘱函,失蹤者是張志新(化名)和其女友劉穎甘畅,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體往弓,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡疏唾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了函似。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片槐脏。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖撇寞,靈堂內(nèi)的尸體忽然破棺而出顿天,到底是詐尸還是另有隱情,我是刑警寧澤蔑担,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布露氮,位于F島的核電站,受9級特大地震影響钟沛,放射性物質(zhì)發(fā)生泄漏畔规。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一恨统、第九天 我趴在偏房一處隱蔽的房頂上張望叁扫。 院中可真熱鬧,春花似錦畜埋、人聲如沸莫绣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽对室。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間掩宜,已是汗流浹背蔫骂。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留牺汤,地道東北人辽旋。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像檐迟,于是被迫代替她去往敵國和親补胚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 什么是類加載機制 JVM把描述類的數(shù)據(jù)從Class文件加載到內(nèi)存追迟,并對數(shù)據(jù)進行校驗溶其、轉(zhuǎn)換解析和初始化,最終形成可以...
    p712long閱讀 168評論 0 0
  • 代碼編譯的結(jié)果從本地機器碼轉(zhuǎn)變?yōu)樽止?jié)碼敦间,是存儲格式發(fā)展的一小步握联,確實編譯語言發(fā)展的一大步。 虛擬機把描述類的數(shù)據(jù)從...
    胡二囧閱讀 945評論 0 0
  • 上篇文章中每瞒,我們介紹了 .class 文件的結(jié)構(gòu)金闽,.class 文件只是一個靜態(tài)的文件,那 JVM 是加載 .cl...
    lijiankun24閱讀 2,976評論 2 9
  • JVM類加載機制 概述 類加載過程 加載 通過類的全限定名獲取類的二進制流 將靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運行時數(shù)據(jù)...
    東溪95閱讀 3,011評論 0 15
  • 有興趣可以先參考前面的幾篇JVM總結(jié): JVM自動內(nèi)存管理機制-Java內(nèi)存區(qū)域(上) JVM自動內(nèi)存管理機制-J...
    零點145閱讀 238評論 0 0