【JVM】HotSpot對象創(chuàng)建官辈、內(nèi)存箱舞、訪問

一 對象創(chuàng)建過程

在Java程序運行中無時無刻都有對象被創(chuàng)建出來,在Java語言層面拳亿,僅僅是一個new關鍵字而已晴股。

而當虛擬機遇到一條new指令時,會進行一序列對象創(chuàng)建的操作肺魁。

1电湘、檢查常量池中是否有即將要創(chuàng)建的這個對象所屬類的符號引用。

1)如果常量池中沒有這個類的符號引用,說明這個類沒有被定義寂呛,則拋出ClassNotFoundException異常怎诫;

2)如果有這個類的符號引用,則進行下步處理贷痪;

2幻妓、檢查這個符號引用所代表的類是否已經(jīng)被JVM加載。

1)如果該類還沒有被加載劫拢,就找到該類的class文件肉津,并加載進方法區(qū);

2)如果該類已經(jīng)被JVM加載舱沧,則準備為對象分配內(nèi)存妹沙;

3、根據(jù)方法區(qū)中該類的信息確定該類所需的內(nèi)存大小狗唉。

對象所需內(nèi)存大小在類加載完成后便可以完全確定初烘,為對象分配空間的任務等同于把一塊確定

大小的內(nèi)存從Java堆中劃分出來。

4分俯、從堆中劃分一塊對應大小的內(nèi)存空間給新的對象肾筐。

分配堆中內(nèi)存有兩種算法方式:

1)指針碰撞

如果JVM垃圾收集器采用復制算法或標記-整理算法等帶整理功能的收集器,則Java堆中的內(nèi)存是絕對規(guī)整的缸剪,

用過的內(nèi)存放在一邊吗铐,空閑的內(nèi)存放在另一邊,中間放著一個指針作為分界點的指示器杏节,那所需要分配的內(nèi)存

就僅僅是把指示器指針向空閑空間那邊挪動一段與對象大小相等的距離唬渗,這種分配方式稱為"指針碰撞"(Bump the Pointer)。

2)空閑列表

如果JVM的垃圾收集器采用標記-清除算法奋渔,Java中內(nèi)存不是規(guī)整的镊逝,已使用內(nèi)存和未使用內(nèi)存相互交錯,

就沒法通過簡單的指針碰撞來為對象分配內(nèi)存嫉鲸,虛擬機針對這種交錯的內(nèi)存維護了一個列表撑蒜,記錄哪些內(nèi)存塊

是可用的,在分配的時候找到一塊足夠大的空間劃分給對象實例玄渗,并更新列表上的記錄座菠,

這種分配方式成為"空閑列表"(Free List)。

總之選擇哪種對象內(nèi)存分配算法是由JVM的垃圾回收算法決定的浴滴。除了劃分內(nèi)存外,還有一個問題岁钓,

虛擬機創(chuàng)建對象非常頻繁升略,即使僅僅是修改一個指針所指向的位置,在并發(fā)情況下也并不是線程安全的品嚣,

可能出現(xiàn)正在給對象A分配內(nèi)存骂远,指針還沒來得及修改,對象B又同時使用了原來的指針分配內(nèi)存的情況腰根。

有兩種方案解決這個問題:

1)對分配內(nèi)存空間的動作做同步處理(虛擬機采用CAS算法配上失敗重試的方式保證更新操作的原子性);

2)把內(nèi)存分配的動作按照線程劃分在不同的空間中進行拓型,即每個線程在Java堆中預先分配一小塊內(nèi)存额嘿,

稱為本地線程分配緩沖(Thread Local Allocation Buffer,TLAB)劣挫。哪個線程要分配內(nèi)存册养,

就在哪個線程的TLAB上分配,只有TLAB用完压固,分配新的TLAB的時候才需要同步鎖定球拦。

虛擬機是否使用TLAB,可以通過-XX:+/-UseTLAB參數(shù)來設定帐我。

5坎炼、內(nèi)存分配完成后,虛擬機需要為對象中的成員變量賦上初始值(默認初始化)拦键。

這么做是為了保證對象的實例字段在Java代碼中可以不賦初始值就直接使用谣光。

6、設置對象頭中的信息芬为。

虛擬機需要對對象進行必要的設置萄金,比如這個對象是哪個類的實例、如何才能找到類的元數(shù)據(jù)信息媚朦、

對象的哈希碼氧敢、對象的GC分代年齡等等。這些信息存放在對象的對象頭(Object Header)中询张。

根據(jù)虛擬機運行狀態(tài)不同孙乖,對象頭也會有不同的設置。

在上面工作完事以后瑞侮,從虛擬機角度看對象已經(jīng)產(chǎn)生了的圆,但是從Java程序看,對象創(chuàng)建才剛剛

開始<init>方法還沒執(zhí)行半火,所有的字段都還為零越妈。所以,一般來說(由字節(jié)碼中是否跟隨invokeSpecial指令所決定)钮糖,

執(zhí)行new命令后會接著執(zhí)行<init>方法梅掠,把對象按照Java程序進行初始化酌住,這樣,真正可用的對象才算完全產(chǎn)生出來阎抒。

總結(jié):

符號引用檢查-->JVM類加載-->對象空間大小確定-->分配內(nèi)存給新對象

-->對象賦初始值-->對象頭信息設置-->最終初始化為真正可用對象酪我。
二 對象內(nèi)存模型

在HotSpot虛擬機中,對象在內(nèi)存中存儲的布局可以分為3塊區(qū)域:

對象頭(Object Header)
實例數(shù)據(jù)(Instance Data)
對齊填充(Padding)

1且叁、對象頭

對象頭包含兩部分信息都哭,第一部分用于存儲對象運行時數(shù)據(jù),如哈希碼(HashCode)逞带、GC分代年齡欺矫、

鎖狀態(tài)標識、線程持有的鎖展氓、偏向線程ID穆趴、偏向時間戳等等。

對象頭的另一部分存儲的是類型指針遇汞,即對象指向它的類元數(shù)據(jù)的指針未妹,虛擬機通過這個指針來

確定這個對象是哪個類的實例。如果對象是一個數(shù)組空入,那么對象頭中還要包含數(shù)組長度络它。
2、實例數(shù)據(jù)

實例數(shù)據(jù)部分就是成員變量的值执庐,其中包含父類的成員變量和本類的成員變量酪耕。
3、對齊填充

對齊填充并不是必然存在的轨淌,也沒有特別的含義迂烁,僅僅起著占位符的作用。HotSpot要求對象的

總長度必須是8字節(jié)的整數(shù)倍递鹉。由于對象頭一定是8字節(jié)的整數(shù)倍盟步,但實例數(shù)據(jù)部分的長度是任意的,

因此需要對齊補充字段確保整個對象的總長度為8的整數(shù)倍躏结。
三 訪問對象過程

我們知道却盘,引用類型的變量中存放的是一個地址,那么根據(jù)地址類型的不同媳拴,對象有不同的訪問方式黄橘。
1、句柄訪問方式

堆中需要有一塊叫做“句柄池”的內(nèi)存空間屈溉,用于存放所有對象的地址和所有對象所屬類的類信息塞关。 

引用類型的變量存放的是該對象在句柄池中的地址。訪問對象時子巾,首先需要通過引用類型的變量找到該對象的句柄帆赢,

然后根據(jù)句柄中對象的地址再訪問對象小压。如圖所示:

2、直接指針訪問方式

如果使用直接指針訪問椰于,那么Java堆對象的布局中就必須考慮如何放置訪問類型數(shù)據(jù)相關信息怠益,

而reference中存儲的直接就是對象地址,從而不需要句柄池瘾婿,通過引用能夠直接訪問對象蜻牢。

但對象所在的內(nèi)存空間中需要額外的策略存儲對象所屬的類信息的地址。如圖所示:

這兩種訪問方式各有優(yōu)勢偏陪,使用句柄訪問的最大好處就是reference中存儲的是穩(wěn)定的句柄地址孩饼,

在對象移動時只會改變句柄中的實例數(shù)據(jù)指針,而虛擬機棧局部變量表里面的reference引用不需要改變竹挡。

使用直接指針訪問方式的最大好處就是速度更快,它節(jié)省了一次指針定位的時間開銷立膛,由于對象的訪問

在Java中非常頻繁揪罕,因此此類開銷累計執(zhí)行成本也不低。HotSpot使用第二種方式進行對象訪問宝泵,

某些語言或框架使用句柄訪問對象的也不少好啰。
————————————————
版權(quán)聲明:本文為CSDN博主「街燈下的校草」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議儿奶,轉(zhuǎn)載請附上原文出處鏈接及本聲明框往。
原文鏈接:https://blog.csdn.net/yhl_jxy/article/details/80893288

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市闯捎,隨后出現(xiàn)的幾起案子椰弊,更是在濱河造成了極大的恐慌,老刑警劉巖瓤鼻,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件秉版,死亡現(xiàn)場離奇詭異,居然都是意外死亡茬祷,警方通過查閱死者的電腦和手機清焕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來祭犯,“玉大人秸妥,你說我怎么就攤上這事∥执郑” “怎么了粥惧?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長陪每。 經(jīng)常有香客問我影晓,道長镰吵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任挂签,我火速辦了婚禮疤祭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘饵婆。我一直安慰自己勺馆,他們只是感情好,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布侨核。 她就那樣靜靜地躺著草穆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪搓译。 梳的紋絲不亂的頭發(fā)上悲柱,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天,我揣著相機與錄音些己,去河邊找鬼豌鸡。 笑死,一個胖子當著我的面吹牛段标,可吹牛的內(nèi)容都是我干的涯冠。 我是一名探鬼主播,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼逼庞,長吁一口氣:“原來是場噩夢啊……” “哼蛇更!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起赛糟,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤派任,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后璧南,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吨瞎,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年穆咐,在試婚紗的時候發(fā)現(xiàn)自己被綠了颤诀。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡对湃,死狀恐怖崖叫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拍柒,我是刑警寧澤心傀,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站拆讯,受9級特大地震影響脂男,放射性物質(zhì)發(fā)生泄漏养叛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一宰翅、第九天 我趴在偏房一處隱蔽的房頂上張望弃甥。 院中可真熱鬧,春花似錦汁讼、人聲如沸淆攻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瓶珊。三九已至,卻和暖如春耸彪,著一層夾襖步出監(jiān)牢的瞬間尼荆,已是汗流浹背晋修。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工崎弃, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留炸茧,地道東北人后雷。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓辑畦,卻偏偏與公主長得像蔓钟,于是被迫代替她去往敵國和親磺箕。 傳聞我的和親對象是個殘疾皇子稽屏,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355

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