一忿危、類加載

jdk

jdk是一套java開發(fā)工具,其中包括了java運行時環(huán)境jre没龙,在jre中有jvm(java虛擬機)铺厨,代碼運行在jvm中

如下圖所示,JVM類加載機制分為五個部分:加載硬纤,驗證解滓,準備,解析筝家,初始化洼裤,下面我們就分別來看一下這五個過程。

類加載過程

1.概述

???????Class文件由類裝載器裝載后溪王,在JVM中將形成一份描述Class結(jié)構(gòu)的元信息對象腮鞍,通過該元信息對象可以獲知Class的結(jié)構(gòu)信息:如構(gòu)造函數(shù),屬性和方法等莹菱,Java允許用戶借由這個Class相關(guān)的元信息對象間接調(diào)用Class對象的功能移国。

????????虛擬機把描述類的數(shù)據(jù)從class文件加載到內(nèi)存,并對數(shù)據(jù)進行校驗道伟,轉(zhuǎn)換解析和初始化迹缀,最終形成可以被虛擬機直接使用的Java類型,這就是虛擬機的類加載機制

2.工作機制

類裝載器就是尋找類的字節(jié)碼文件蜜徽,并構(gòu)造出類在JVM內(nèi)部表示的對象組件祝懂。在Java中,類裝載器把一個類裝入JVM中拘鞋,要經(jīng)過以下步驟:

(1)?裝載:查找和導(dǎo)入Class文件砚蓬;

(2)?鏈接:把類的二進制數(shù)據(jù)合并到JRE中;

?(a)校驗:檢查載入Class文件數(shù)據(jù)的正確性掐禁;

?(b)準備:給類的靜態(tài)變量分配存儲空間怜械;

?(c)解析:將符號引用轉(zhuǎn)成直接引用;

(3)?初始化:對類的靜態(tài)變量傅事,靜態(tài)代碼塊執(zhí)行初始化操作

【裝載】

?在裝載階段缕允,虛擬機需要完成以下3件事情

????????(1)?通過一個類的全限定名來獲取定義此類的二進制字節(jié)流

????????(2)?將這個字節(jié)流所代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運行時數(shù)據(jù)結(jié)構(gòu)

????????(3)?在Java堆中生成一個代表這個類的java.lang.Class對象,作為方法區(qū)這些數(shù)據(jù)的訪問入口蹭越。

虛擬機規(guī)范中并沒有準確說明二進制字節(jié)流應(yīng)該從哪里獲取以及怎樣獲取,這里可以通過定義自己的類加載器去控制字節(jié)流的獲取方式障本。注意這里不一定非得要從一個Class文件獲取,這里既可以從ZIP包中讀取(比如從jar包和war包中讀燃菟)案训,也可以在運行時計算生成(動態(tài)代理),也可以由其它文件生成(比如將JSP文件轉(zhuǎn)換成對應(yīng)的Class類)粪糙。

【驗證】

????虛擬機如果不檢查輸入的字節(jié)流强霎,對其完全信任的話,很可能會因為載入了有害的字節(jié)流而導(dǎo)致系統(tǒng)奔潰蓉冈。

【準備】

準備階段是正式為類變量分配內(nèi)存并設(shè)置類變量的初始值階段城舞,即在方法區(qū)中分配這些變量所使用的內(nèi)存空間。注意這里所說的初始值概念寞酿,比如一個類變量定義為:

public static int v = 8080;

實際上變量v在準備階段過后的初始值為0而不是8080家夺,將v賦值為8080的putstatic指令是程序被編譯后,存放于類構(gòu)造器方法之中伐弹,這里我們后面會解釋拉馋。

但是注意如果聲明為:

public static final int v = 8080;

在編譯階段會為v生成ConstantValue屬性,在準備階段虛擬機會根據(jù)ConstantValue屬性將v賦值為8080惨好。

【解析】

解析階段是指虛擬機將常量池中的符號引用替換為直接引用的過程煌茴。符號引用就是class文件中的:

CONSTANT_Class_info

CONSTANT_Field_info

CONSTANT_Method_info

等類型的常量。

下面我們解釋一下符號引用和直接引用的概念:

符號引用與虛擬機實現(xiàn)的布局無關(guān)昧狮,引用的目標并不一定要已經(jīng)加載到內(nèi)存中景馁。各種虛擬機實現(xiàn)的內(nèi)存布局可以各不相同,但是它們能接受的符號引用必須是一致的逗鸣,因為符號引用的字面量形式明確定義在Java虛擬機規(guī)范的Class文件格式中。

直接引用可以是指向目標的指針绰精,相對偏移量或是一個能間接定位到目標的句柄撒璧。如果有了直接引用,那引用的目標必定已經(jīng)在內(nèi)存中存在笨使。

【類初始化】

??????(1)?遇到new卿樱、getstatic、putstatic或invokestatic這4條字節(jié)碼指令時硫椰,如果類沒有進行過初始化繁调,則需要先觸發(fā)其初始化。生成這4條指令的最常見的Java代碼場景是:使用new關(guān)鍵字實例化對象的時候靶草,讀取或設(shè)置一個類的靜態(tài)字段(被final修飾蹄胰、已在編譯期把結(jié)果放入常量池的靜態(tài)字段除外)的時候,以及調(diào)用一個類的靜態(tài)方法的時候奕翔。

??????(2)?使用java.lang.reflect包的方法對類進行反射調(diào)用的時候裕寨,如果類沒有進行過初始化,則需要先觸發(fā)其初始化。

??????(3)?當初始化一個類的時候宾袜,如果發(fā)現(xiàn)其父類還沒有進行過初始化捻艳,則需要先觸發(fā)其父類的初始化。

? ? ? (4)當虛擬機啟動時庆猫,用戶需要指定一個要執(zhí)行的主類(包含main()方法的那個類)认轨,虛擬機會先初始化這個主類。

只有上述四種情況會觸發(fā)初始化月培,也稱為對一個類進行主動引用嘁字,除此以外,所有其他方式都不會觸發(fā)初始化节视,稱為被動引用

代碼清單1

被動初始化

上述代碼運行后拳锚,只會輸出【---SuperClass?init】,?而不會輸出【SubClass?init】,對于靜態(tài)字段,只有直接定義這個字段的類才會被初始化,因此寻行,通過子類來調(diào)用父類的靜態(tài)字段霍掺,只會觸發(fā)父類的初始化,但是這是要看不同的虛擬機的不同實現(xiàn)。

代碼清單2

被動初始化

此處不會引起SuperClass的初始化拌蜘,但是卻觸發(fā)了【[Ltest.SuperClass】的初始化杆烁,通過arr.toString()可以看出,對于用戶代碼來說简卧,這不是一個合法的類名稱兔魂,它是由虛擬機自動生成的,直接繼承于Object的子類举娩,創(chuàng)建動作由字節(jié)碼指令newarray觸發(fā),此時數(shù)組越界檢查也會伴隨數(shù)組對象的所有調(diào)用過程析校,越界檢查并不是封裝在數(shù)組元素訪問的類中,而是封裝在數(shù)組訪問的xaload,xastore字節(jié)碼指令中.

代碼清單3

被動初始化

對常量ConstClass.value?的引用實際都被轉(zhuǎn)化為NotInitialization類對自身常量池的引用铜涉,這兩個類被編譯成class后不存在任何聯(lián)系智玻。


示例題:類加載器與類的”相同“判斷

類加載器除了用于加載類外,還可用于確定類在Java虛擬機中的唯一性芙代。

即便是同樣的字節(jié)代碼吊奢,被不同的類加載器加載之后所得到的類,也是不同的纹烹。

通俗一點來講页滚,要判斷兩個類是否“相同”,前提是這兩個類必須被同一個類加載器加載铺呵,否則這個兩個類不“相同”裹驰。

這里指的“相同”,包括類的Class對象的equals()方法陪蜻、isAssignableFrom()方法邦马、isInstance()方法、instanceof關(guān)鍵字等判斷出來的結(jié)果。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末滋将,一起剝皮案震驚了整個濱河市邻悬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌随闽,老刑警劉巖父丰,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異掘宪,居然都是意外死亡蛾扇,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門魏滚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來镀首,“玉大人,你說我怎么就攤上這事鼠次「澹” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵腥寇,是天一觀的道長成翩。 經(jīng)常有香客問我,道長赦役,這世上最難降的妖魔是什么麻敌? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮掂摔,結(jié)果婚禮上术羔,老公的妹妹穿的比我還像新娘。我一直安慰自己乙漓,他們只是感情好聂示,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著簇秒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪秀鞭。 梳的紋絲不亂的頭發(fā)上趋观,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機與錄音锋边,去河邊找鬼皱坛。 笑死,一個胖子當著我的面吹牛豆巨,可吹牛的內(nèi)容都是我干的剩辟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼贩猎!你這毒婦竟也來了熊户?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤吭服,失蹤者是張志新(化名)和其女友劉穎嚷堡,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體艇棕,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡蝌戒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了沼琉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片北苟。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖打瘪,靈堂內(nèi)的尸體忽然破棺而出友鼻,到底是詐尸還是另有隱情,我是刑警寧澤瑟慈,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布桃移,位于F島的核電站,受9級特大地震影響葛碧,放射性物質(zhì)發(fā)生泄漏借杰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一进泼、第九天 我趴在偏房一處隱蔽的房頂上張望蔗衡。 院中可真熱鬧,春花似錦乳绕、人聲如沸绞惦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽济蝉。三九已至,卻和暖如春菠发,著一層夾襖步出監(jiān)牢的瞬間王滤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工滓鸠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留雁乡,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓糜俗,卻偏偏與公主長得像踱稍,于是被迫代替她去往敵國和親曲饱。 傳聞我的和親對象是個殘疾皇子肝陪,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353