java虛擬機學(xué)習(xí)筆記3-----對象的內(nèi)存布局和對象的訪問定位

對象的內(nèi)存布局

????????在HotSpot虛擬機中,對象在內(nèi)存中存儲的布局可以分為三塊區(qū)域:對象頭、實例數(shù)據(jù)、對齊填充。

對象頭

????HotSpot虛擬機中的對象頭包括兩部分內(nèi)容: ?

?????????第一部分用于存儲對象自身的運行時數(shù)據(jù),如哈希碼、GC分代年齡、鎖標(biāo)識狀態(tài)、線程持有的鎖、偏向線程ID、偏向時間戳等,因為對象的運行時數(shù)據(jù)很多,所以存儲的結(jié)構(gòu)并不固定。

??????????第二部分是類型指針,即對象執(zhí)行她類元數(shù)據(jù)的指針,虛擬機通過這個指針來確定對象屬于哪個類的實例。(并不是所有的虛擬機實現(xiàn)都必須在對象數(shù)據(jù)上保留類型指針,換句話說,查找對象的類元數(shù)據(jù)并不一定通過對象本身)。如果對象是一個數(shù)組,那么在對象頭中還要存儲數(shù)組的長度。

實例數(shù)據(jù)

????????實例數(shù)據(jù)部分是對象真正儲存的有效信息,也就是在程序代碼中所定義的各種類型的字段內(nèi)容,無論是從父類繼承來的,還是在子類定義的,都需要記錄起來。存儲順序受虛擬機分配策略參數(shù)所影響,HotSpot虛擬機默認(rèn)的分配策略為longs/doubles、ints、shorts/chars、bytes/booleans、ops,從分配策略可以看出,相同寬度的字段總是在一起,在滿足這個條件的情況下,父類中定義的元素會出現(xiàn)在子類之前

對齊填充

????????第三部分的對齊填充數(shù)據(jù)不是必須出現(xiàn)的,也沒有特別的含義,他僅僅起著占位符的作用(由于Hotspot VM的自動內(nèi)存管理喜用要求對象的起始地址必須是8字節(jié)的整數(shù)倍,就是對象的大小不惜是8字節(jié)的整數(shù)倍,所以就需要對齊填充數(shù)據(jù)了)

關(guān)于對象大小的計算

引用自?點我

32 位系統(tǒng)下,當(dāng)使用 new Object() 時,JVM 將會分配 8(Mark Word+類型指針) 字節(jié)的空間,128 個 Object 對象將占用 1KB 的空間。如果是 new Integer(),那么對象里還有一個 int 值,其占用 4 字節(jié),這個對象也就是 8+4=12 字節(jié),對齊后,該對象就是 16 字節(jié)。以上只是一些簡單的對象,那么對象的內(nèi)部屬性是怎么排布的?

Class A {

int i; ?byte b; ? ? ? String str; }

其中對象頭部占用 ‘Mark Word’4 + ‘類型指針’4 = 8 字節(jié);byte 8 位長,占用 1 字節(jié);int 32 位長,占用 4 字節(jié);String 只有引用,占用 4 字節(jié);那么對象 A 一共占用了 8+1+4+4=17 字節(jié),按照 8 字節(jié)對齊原則,對象大小也就是 24 字節(jié)。這個計算看起來是沒有問題的,對象的大小也確實是 24 字節(jié),但是對齊(padding)的位置并不對:在 HotSpot VM 中,對象排布時,間隙是在 4 字節(jié)基礎(chǔ)上的(在 32 位和 64 位壓縮模式下),上述例子中,int 后面的 byte,空隙只剩下 3 字節(jié),接下來的 String 對象引用需要 4 字節(jié)來存放,因此 byte 和對象引用之間就會有 3 字節(jié)對齊,對象引用排布后,最后會有 4 字節(jié)對齊,因此結(jié)果上依然是 7 字節(jié)對齊, 此時對象的結(jié)構(gòu)示意圖,如下圖所示:


對象的訪問定位

????????我們的java程序需要通過棧上的reference數(shù)據(jù)來操作堆上的具體對象,而對象的訪問方式由虛擬機實現(xiàn)來決定,目前主流的訪問方式有句柄和直接指針兩種。

句柄

? ? ? ? 使用句柄的方式,java堆中將會劃分出一塊內(nèi)存來作為句柄池,reference中存儲的就是對象的句柄池地址,而句柄池中包含了對象實例數(shù)據(jù)與類型數(shù)據(jù)各自的具體地址信息。


句柄方式


直接指針

? ? ? ? 使用直接指針訪問,reference存儲的就是對象的地址,而java堆中的對象不僅保存中對象的實例數(shù)據(jù),還引用了對象的類型數(shù)據(jù)。


直接指針

兩種方式各有優(yōu)勢:

? ? 1。句柄的方式最大的好處就是存儲的是句柄的地址,當(dāng)對象移動時不需要改變引用地址(垃圾回收時對象移動是很頻繁的事情),只改變句柄中實例數(shù)據(jù)的指針,但這需要頻繁的移動指針。

? ? 2.直接指針的方式最大的好處就是速度更快,她節(jié)省了一次指針定位的時間開銷,由于對象的訪問很頻繁的事情,積少成多也可以節(jié)約許多時間成本。

而對于虛擬機sun Hotspot而言,他使用的是直接指針的方式來進行對象訪問的。

一篇關(guān)于JVM內(nèi)存分配模型的概念講的很好的文章:內(nèi)存模型


當(dāng)它本可進取時,卻故作謙卑;

當(dāng)它在空虛時,用愛欲來填充;

在困難和容易之間,它選擇了容易;

它犯了錯,卻借由別人也會犯錯來寬慰自己;

它自由軟弱,卻把它認(rèn)為是生命的堅韌;

當(dāng)它鄙夷一張丑惡的嘴臉時,卻不知那正是自己面具中的一副;

它側(cè)身于生活的污泥中,雖不甘心,卻又畏首畏尾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容