Java類加載機(jī)制-筆記2(類加載的過程)

1.類加載的目的:

一份被javac編譯過的class文本文件通過加載仰美,生成某種形式的Class數(shù)據(jù)結(jié)構(gòu)進(jìn)入內(nèi)存猾骡, 程序可以調(diào)用這個(gè)數(shù)據(jù)結(jié)構(gòu)來構(gòu)造出object即硼,這個(gè)過程是在運(yùn)行時(shí)進(jìn)行的钞诡,也是java動態(tài)拓展性的根基羡微。

一個(gè)類的生命周期:

  1. javac 編譯
  2. 加載
  3. 鏈接
  4. 初始化
  5. 使用
  6. 卸載

類加載包含了三個(gè)階段

  1. 加載
  2. 鏈接
  3. 初始化

鏈接包含三個(gè)步驟:

  • 驗(yàn)證
  • 準(zhǔn)備
  • 解析

其中傻唾,解析步驟是靈活的投慈,他可以在初始化之前或者之后再進(jìn)行,實(shí)現(xiàn)所謂的‘后期綁定’策吠,其他環(huán)節(jié)則是不可改變的逛裤。

2.類加載的階段

加載
加載是一個(gè)讀取Class文件,將其轉(zhuǎn)化為某種靜態(tài)數(shù)據(jù)結(jié)構(gòu)存儲在方法區(qū)內(nèi)猴抹,并在堆中生成一個(gè)便于用戶調(diào)用的java.lang.Class類型的對象的過程带族。

注意:
這里的Class文件不僅僅是指的本地文件,泛指各種來源的二進(jìn)制流蟀给,比如從網(wǎng)絡(luò)蝙砌、數(shù)據(jù)庫、即時(shí)計(jì)算出來的class文件跋理,比如著名的就是 動態(tài)代理技術(shù)择克,就是使用到了即時(shí)計(jì)算出來的class,然后實(shí)例化代理對象前普,可以自由選擇二進(jìn)制流肚邢。

鏈接
  • 驗(yàn)證

驗(yàn)證動作是有很多個(gè)步驟的,包括:文件格式驗(yàn)證拭卿、元數(shù)據(jù)字節(jié)碼驗(yàn)證骡湖、符號引用驗(yàn)證。
文件格式驗(yàn)證:其實(shí)是發(fā)生在加載階段的峻厚,如果通過响蕴,那么才能順利加載,順利加載后此時(shí)方法區(qū)內(nèi)雖然已經(jīng)存在了該class的靜態(tài)結(jié)構(gòu)惠桃,堆中也存在了該class類型的對象浦夷,但是這并不代表著JVM已經(jīng)完全認(rèn)可了這個(gè)類辖试。如果程序想要使用這個(gè)類那么就必須進(jìn)行鏈接,而鏈接的第一步就是進(jìn)一步對這個(gè)類進(jìn)行驗(yàn)證劈狐,到底對方法區(qū)內(nèi)的class靜態(tài)結(jié)構(gòu)進(jìn)行了哪些方面的驗(yàn)證罐孝。

元數(shù)據(jù)的驗(yàn)證、字節(jié)碼的驗(yàn)證:就是對class的靜態(tài)結(jié)構(gòu)進(jìn)行語法和語義上的分析懈息,保證其不會產(chǎn)生危害虛擬機(jī)的行為肾档。這兩個(gè)步驟驗(yàn)證通過,那么虛擬機(jī)會姑且認(rèn)為該class是安全的辫继,但是這并不意味著驗(yàn)證已經(jīng)完全結(jié)束了,還有一道對符號引用進(jìn)行驗(yàn)證的步驟俗慈。
符號引用驗(yàn)證:它是在解析階段內(nèi)發(fā)生的姑宽,而解析階段我們之前也提到過,它可以在初始化階段之前或者之后進(jìn)行闺阱。
驗(yàn)證其實(shí)包含了很多的步驟炮车,分散在各個(gè)不同的階段內(nèi),驗(yàn)證的內(nèi)容是會不斷發(fā)展的酣溃,除了這里提到的文本格式驗(yàn)證瘦穆、元數(shù)據(jù)字節(jié)碼驗(yàn)證、符號引用驗(yàn)證 四個(gè)環(huán)節(jié) 從低版本的虛擬機(jī)到現(xiàn)在 驗(yàn)證步驟其實(shí)已經(jīng)不斷的加入了各種機(jī)制赊豌。在未來扛或,虛擬機(jī)的開發(fā)人員可能會引入更多更完善更完美的策略。

  • 準(zhǔn)備

在元數(shù)據(jù)碘饼、字節(jié)碼驗(yàn)證通過之后熙兔,虛擬機(jī)會姑且認(rèn)為該class是安全的,這時(shí)候會進(jìn)入準(zhǔn)備階段艾恼,準(zhǔn)備階段做的處理住涉,并不復(fù)雜,就是為該類型中定義的靜態(tài)變量賦0值钠绍,注意舆声,這里僅僅是靜態(tài)變量而不是成員變量,此時(shí)將會出現(xiàn)一個(gè)被太多人混淆和誤解的概念柳爽,我們這里就好好捋一捋媳握。
虛擬機(jī)內(nèi)存規(guī)范中的定義了方法區(qū)這種抽象概念,HotSpot這種主流虛擬機(jī)在JDK8之前使用了永久代這種具體的實(shí)現(xiàn)方式來實(shí)現(xiàn)方法區(qū)泻拦。在JDK8之后毙芜,棄用‘永久代’這種實(shí)現(xiàn)方式,采用元空間這種直接內(nèi)存取代争拐。
在JDK8之前腋粥,類的元信息晦雨、常量池、靜態(tài)變量等都存儲在 永久代這種具體實(shí)現(xiàn)中隘冲,而在JDK8及之后闹瞧,常量池、靜態(tài)變量被移除‘方法區(qū)’展辞,轉(zhuǎn)移到了堆中奥邮,元信息這些呢,依然保留在方法區(qū)內(nèi)罗珍,但是具體的存儲方式改成了元空間洽腺。

  • 解析

該階段主要做的事情是將 符號引用 替換為 直接引用。什么是符號引用覆旱,什么是直接引用蘸朋?
當(dāng)一個(gè)Java類被編譯成Class之后,假如這個(gè)類稱為A扣唱,并且A中 引用了B藕坯,那么在編譯階段,A是不知道B有沒有被編譯的噪沙,而且此時(shí)B也一定沒有被加載炼彪,所以A肯定不知道B的實(shí)際地址,那么A怎么才能找到B呢正歼?辐马,此時(shí)在A的class文件中,將使用一個(gè)字符串S來代表B的地址朋腋,S就被稱為符號引用齐疙,在運(yùn)行時(shí)呢,如果A發(fā)生了類加載旭咽,到了解析階段會發(fā)現(xiàn)B還未被加載贞奋,那么將會觸發(fā)B的類加載,將B加載到虛擬機(jī)中穷绵,此時(shí)A中的B的符號引用將會被替換成B的實(shí)際地址轿塔,這被稱為直接引用,這樣也就能夠真正的調(diào)用B了仲墨。
Java通過后期綁定的方式來實(shí)現(xiàn)多態(tài)勾缭,那么后期綁定這個(gè)概念,又是如何實(shí)現(xiàn)的呢目养?
其實(shí)就是這里的動態(tài)解析俩由,如果A調(diào)用的B是一個(gè)具體的實(shí)現(xiàn)類,那么就稱為靜態(tài)解析癌蚁,因?yàn)榻忉尩哪繕?biāo)類型很明確幻梯,而假如上層Java代碼使用了多態(tài)兜畸,這里的B是一個(gè)抽象類或者是接口,那么 B可能有兩個(gè)具體的實(shí)現(xiàn)類C和D 此時(shí)碘梢,B的具體實(shí)現(xiàn)并不明確咬摇,當(dāng)然也就不知道使用哪個(gè)具體類的直接引用來進(jìn)行替換,既然不知道煞躬,那么就等一等吧肛鹏,直到運(yùn)行過程中發(fā)生了調(diào)用,此時(shí)虛擬機(jī)調(diào)用棧中將會得到具體的類型信息恩沛,這時(shí)候再進(jìn)行解析在扰,就能用明確的直接引用來替換符號引用,這就解釋了為什么解析階段有時(shí)候會發(fā)生在初始化階段之后复唤,這就是動態(tài)解析健田,用它來實(shí)現(xiàn)了后期綁定。底層對應(yīng)了invokedynamic這條字節(jié)碼指令佛纫。

擴(kuò)展:多態(tài)

擴(kuò)展:動態(tài)綁定

初始化

初始化階段簡單概括:此時(shí)會判斷代碼中是否存在主動的資源初始化操作,如果有的話总放,那么執(zhí)行呈宇。這里所說的主動的資源初始化動作,不是指的構(gòu)造函數(shù)局雄,而是class層面的甥啄,比如說成員變量的賦值動作,靜態(tài)變量的賦值動作炬搭,以及靜態(tài)代碼塊的邏輯蜈漓。而只有顯式的調(diào)用new指令 才會調(diào)用構(gòu)造函數(shù)進(jìn)行對象的實(shí)例化,這是對象層面的宫盔,二者不能進(jìn)行混淆融虽。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市灼芭,隨后出現(xiàn)的幾起案子有额,更是在濱河造成了極大的恐慌,老刑警劉巖彼绷,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件巍佑,死亡現(xiàn)場離奇詭異,居然都是意外死亡寄悯,警方通過查閱死者的電腦和手機(jī)萤衰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來猜旬,“玉大人脆栋,你說我怎么就攤上這事倦卖。” “怎么了筹吐?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵糖耸,是天一觀的道長。 經(jīng)常有香客問我丘薛,道長嘉竟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任洋侨,我火速辦了婚禮舍扰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘希坚。我一直安慰自己边苹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布裁僧。 她就那樣靜靜地躺著个束,像睡著了一般。 火紅的嫁衣襯著肌膚如雪聊疲。 梳的紋絲不亂的頭發(fā)上茬底,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天,我揣著相機(jī)與錄音获洲,去河邊找鬼阱表。 笑死,一個(gè)胖子當(dāng)著我的面吹牛贡珊,可吹牛的內(nèi)容都是我干的最爬。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼门岔,長吁一口氣:“原來是場噩夢啊……” “哼爱致!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起固歪,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蒜鸡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后牢裳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逢防,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年蒲讯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了忘朝。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡判帮,死狀恐怖局嘁,靈堂內(nèi)的尸體忽然破棺而出溉箕,到底是詐尸還是另有隱情,我是刑警寧澤悦昵,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布肴茄,位于F島的核電站,受9級特大地震影響但指,放射性物質(zhì)發(fā)生泄漏寡痰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一棋凳、第九天 我趴在偏房一處隱蔽的房頂上張望拦坠。 院中可真熱鬧,春花似錦剩岳、人聲如沸贞滨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽晓铆。三九已至,卻和暖如春绰播,著一層夾襖步出監(jiān)牢的瞬間尤蒿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工幅垮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人尾组。 一個(gè)月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓忙芒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親讳侨。 傳聞我的和親對象是個(gè)殘疾皇子呵萨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評論 2 354

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