JVM源碼分析之Java對(duì)象的創(chuàng)建過程

轉(zhuǎn)載請(qǐng)注明原創(chuàng)出處,謝謝卷哩!
簡(jiǎn)書占小狼
http://www.reibang.com/users/90ab66c248e6/latest_articles

乘著年輕揍障,多學(xué)習(xí)

接著上篇《JVM源碼分析之Java類加載過程》敢靡,本文將基于HotSpot實(shí)現(xiàn)對(duì)Java對(duì)象的創(chuàng)建過程進(jìn)行深入分析脾拆。

定義兩個(gè)簡(jiǎn)單的類AAA和BBB


通過``javap -c AAA```查看編譯之后的字節(jié)碼,具體如下:

Java中的new關(guān)鍵字對(duì)應(yīng)jvm中的new指令岖食,定義在InterpreterRuntime類中红碑,實(shí)現(xiàn)如下:

new指令的實(shí)現(xiàn)過程:
1、其中pool是AAA的constant pool县耽,此時(shí)AAA的class已經(jīng)加載到虛擬機(jī)中句喷,new指令后面的#2表示BBB類全限定名的符號(hào)引用在constant pool的位置;
2兔毙、方法pool->klass_at負(fù)責(zé)返回BBB對(duì)應(yīng)的klassOop對(duì)象唾琼,實(shí)現(xiàn)如下:

如果常量池中指定位置(#2)的數(shù)據(jù)已經(jīng)是個(gè)oop類型,說明BBB的class已經(jīng)被加載并解析過澎剥,則直接通過(klassOop)entry.get_oop()返回klassOop锡溯;否則表示第一次使用BBB,需要解析BBB的符號(hào)引用哑姚,并加載BBB的class類祭饭,生成對(duì)應(yīng)的instanceKlass對(duì)象,并更新constant pool中對(duì)應(yīng)位置的符號(hào)引用叙量;
3倡蝙、klass->check_valid_for_instantiation可以防止抽象類被實(shí)例化;
4绞佩、klass->initialize實(shí)現(xiàn)如下:

如果BBB的instanceKlass對(duì)象已經(jīng)初始化完成寺鸥,則直接返回;否則通過initialize_impl方法進(jìn)行初始化品山,整個(gè)初始化算法分成11步胆建,具體實(shí)現(xiàn)如下:

step1

通過ObjectLocker在初始化之前進(jìn)行加鎖,防止多個(gè)線程并發(fā)初始化肘交。

step2

如果當(dāng)前instanceKlass處于being_initialized狀態(tài)笆载,且正在被其它線程初始化,則執(zhí)行ol.waitUninterruptibly等待其他線程完成后通知。

step3

如果當(dāng)前instanceKlass處于being_initialized狀態(tài)凉驻,且被當(dāng)前線程初始化腻要,則直接返回。
其實(shí)對(duì)于這個(gè)step的處理我有疑問沿侈,什么情況會(huì)走到這一步闯第?經(jīng)過RednaxelaFX大大提點(diǎn),如下情況會(huì)執(zhí)行step3:
例如A類有靜態(tài)變量指向一個(gè)new B類實(shí)例缀拭,B類里又有靜態(tài)變量指向new A類實(shí)例,這樣外部用A時(shí)要初始化A類填帽,初始化過程中又要觸發(fā)B類初始化蛛淋,B類初始化又再次觸發(fā)A類初始化。

step4

如果當(dāng)前instanceKlass處于fully_initialized狀態(tài)篡腌,說明已經(jīng)初始化完成褐荷,則直接返回;

step5

如果當(dāng)前instanceKlass處于initialization_error狀態(tài)嘹悼,說明初始化失敗了叛甫,拋出異常。

step6

設(shè)置當(dāng)前instanceKlass的狀態(tài)為 being_initialized杨伙;設(shè)置初始化線程為當(dāng)前線程其监。

如果當(dāng)前instanceKlass不是接口類型,并且父類不為空限匣,且還未初始化抖苦,則執(zhí)行父類的初始化。

step8

通過this_oop->call_class_initializer方法執(zhí)行靜態(tài)塊代碼米死,實(shí)現(xiàn)如下:

this_oop->class_initializer()可以獲取靜態(tài)代碼塊入口锌历,最終通過JavaCalls::call執(zhí)行代碼塊邏輯,再下一層就是具體操作系統(tǒng)的實(shí)現(xiàn)了峦筒。

step9

如果初始化過程沒有異常究西,說明instanceKlass對(duì)象已經(jīng)初始完成,則設(shè)置當(dāng)前instanceKlass的狀態(tài)為 fully_initialized物喷,最后通知其它線程初始化已經(jīng)完成卤材;否則執(zhí)行step10 and 11。

step10 and 11

如果初始化發(fā)生異常脯丝,則設(shè)置當(dāng)前instanceKlass的狀態(tài)為 initialization_error商膊,并通知其它線程初始化發(fā)生異常。

5宠进、如果instanceKlass初始化完成晕拆,klass->allocate_instance會(huì)在堆內(nèi)存創(chuàng)建instanceOopDesc對(duì)象,即類的實(shí)例化;

instanceOopDesc

當(dāng)在Java中new一個(gè)對(duì)象時(shí)实幕,本質(zhì)是在堆內(nèi)存創(chuàng)建一個(gè)instanceOopDesc對(duì)象吝镣。


instanceOopDesc在實(shí)現(xiàn)上繼承自oopDesc,其中oopDesc定義如下:

當(dāng)然昆庇,這只是 oopDesc的部分實(shí)現(xiàn)末贾,oopDesc包含兩個(gè)數(shù)據(jù)成員:_mark 和 _metadata。
1整吆、_mark是markOop類型對(duì)象拱撵,用于存儲(chǔ)對(duì)象自身的運(yùn)行時(shí)數(shù)據(jù),如哈希碼(HashCode)表蝙、GC分代年齡拴测、鎖狀態(tài)標(biāo)志、線程持有的鎖府蛇、偏向線程ID集索、偏向時(shí)間戳等等,占用內(nèi)存大小與虛擬機(jī)位長(zhǎng)一致汇跨,更具體的實(shí)現(xiàn)可以閱讀 《java對(duì)象頭的HotSpot實(shí)現(xiàn)分析》
2务荆、_metadata是一個(gè)聯(lián)合體,其中wideKlassOop和narrowOop都是指向InstanceKlass對(duì)象的指針穷遂,wide版是普通指針函匕,narrow版是壓縮類指針(compressed Class pointer)

instanceOopDesc對(duì)象的創(chuàng)建過程

instanceOopDesc對(duì)象通過instanceKlass::allocate_instance進(jìn)行創(chuàng)建,實(shí)現(xiàn)過程如下:
1塞颁、has_finalizer判斷當(dāng)前類是否包含不為空的finalize方法浦箱;
2、size_helper確定創(chuàng)建當(dāng)前對(duì)象需要分配多大內(nèi)存祠锣;
3酷窥、CollectedHeap::obj_allocate從堆中申請(qǐng)指定大小的內(nèi)存,并創(chuàng)建instanceOopDesc對(duì)象伴网,實(shí)現(xiàn)如下:

4蓬推、如果當(dāng)前類重寫了finalize方法,且非空澡腾,需要把生成的對(duì)象封裝成Finalizer對(duì)象并添加到 Finalizer鏈表中沸伏,對(duì)象被GC時(shí),如果是Finalizer對(duì)象动分,會(huì)將對(duì)象賦值到pending對(duì)象毅糟。Reference Handler線程會(huì)將pending對(duì)象push到queue中,F(xiàn)inalizer線程poll到對(duì)象澜公,先刪除掉Finalizer鏈表中對(duì)應(yīng)的對(duì)象姆另,然后再執(zhí)行對(duì)象的finalize方法;


我是占小狼
坐標(biāo)魔都,白天上班族迹辐,晚上是知識(shí)的分享者
如果讀完覺得有收獲的話蝶防,歡迎點(diǎn)贊加關(guān)注

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市明吩,隨后出現(xiàn)的幾起案子间学,更是在濱河造成了極大的恐慌,老刑警劉巖印荔,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件低葫,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡仍律,警方通過查閱死者的電腦和手機(jī)氮采,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來染苛,“玉大人,你說我怎么就攤上這事主到〔栊校” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵登钥,是天一觀的道長(zhǎng)畔师。 經(jīng)常有香客問我,道長(zhǎng)牧牢,這世上最難降的妖魔是什么看锉? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮塔鳍,結(jié)果婚禮上伯铣,老公的妹妹穿的比我還像新娘。我一直安慰自己轮纫,他們只是感情好腔寡,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著掌唾,像睡著了一般放前。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上糯彬,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天凭语,我揣著相機(jī)與錄音,去河邊找鬼撩扒。 笑死似扔,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播虫几,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼锤灿,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了辆脸?” 一聲冷哼從身側(cè)響起但校,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎啡氢,沒想到半個(gè)月后状囱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡倘是,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年亭枷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搀崭。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡叨粘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瘤睹,到底是詐尸還是另有隱情升敲,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布轰传,位于F島的核電站驴党,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏获茬。R本人自食惡果不足惜港庄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望恕曲。 院中可真熱鬧鹏氧,春花似錦、人聲如沸码俩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽稿存。三九已至笨篷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瓣履,已是汗流浹背率翅。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留袖迎,地道東北人冕臭。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓腺晾,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親辜贵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子悯蝉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

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

  • ?“365篇原創(chuàng)計(jì)劃”第十一篇垮庐。 今天呢寺惫!燈塔君跟大家講: JVM源碼分析之Java對(duì)象頭實(shí)現(xiàn) HotSpot虛擬...
    猿燈塔閱讀 264評(píng)論 0 1
  • 對(duì)象創(chuàng)建 例子 首先看一個(gè)例子: 編譯之后尔苦,用javap -c AAA來看對(duì)應(yīng)的字節(jié)碼: 可以看到都哭,4-8行是構(gòu)造...
    AlanKim閱讀 356評(píng)論 0 2
  • 之前對(duì)Java對(duì)象的創(chuàng)建一直都是概念上的了解,沒有在源碼層面進(jìn)行過分析最住,這段時(shí)間在看HotSpot遍烦,就順便了解了下...
    半棧工程師閱讀 475評(píng)論 0 0
  • 創(chuàng)建java對(duì)象的方式 java對(duì)象的創(chuàng)建有多種狭姨,最簡(jiǎn)單的是new XXClass婆硬,還可以通過反射狠轻,xx.clo...
    tracy_668閱讀 1,279評(píng)論 0 8
  • 表情是什么,我認(rèn)為表情就是表現(xiàn)出來的情緒彬犯。表情可以傳達(dá)很多信息向楼。高興了當(dāng)然就笑了,難過就哭了谐区。兩者是相互影響密不可...
    Persistenc_6aea閱讀 125,311評(píng)論 2 7