2)java虛擬機中對象的內(nèi)存布局

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

  • 對象頭(Object Header)
    • 存儲對象自身的運行時數(shù)據(jù):如HashCode、GC分代年齡、鎖狀態(tài)標志、線程持有的鎖、偏向線程ID、偏向時間戳等
      這部分數(shù)據(jù)的長度在32位和64位的虛擬機(未開啟壓縮指針)中分別為32bit和64bit,官方稱它為"MarkWord"。對象需要存儲的運行時數(shù)據(jù)很多,其實已經(jīng)超出了32位、64位Bitmap結(jié)構(gòu)所能記錄的限度,但是對象頭信息是與對象自身定義的數(shù)據(jù)無關(guān)的額外存儲成本,考慮到虛擬機的空間效率,MarkWord被設(shè)計成一個非固定的數(shù)據(jù)結(jié)構(gòu)以便在極小的空間內(nèi)存儲盡量多的信息,它會根據(jù)對象的狀態(tài)復(fù)用自己的存儲空間。例如,在32位的HotSpot虛擬機中,如果對象處于未被鎖定的狀態(tài)下,那么MarkWord的32bit空間中的25bit用于存儲對象哈希碼,4bit用于存儲對象分代年齡,2bit用于存儲鎖標志位,1bit固定為0,而在其他狀態(tài)(輕量級鎖定、重量級鎖定、GC標記、可偏向)下對象的存儲內(nèi)容見表2-1。
    • 類型指針(即對象指向它的類元數(shù)據(jù)的指針):虛擬機通過這個指針來確定這個對象是哪個類的實例。(注:并不是所有虛擬機的實現(xiàn)都必須在對象數(shù)據(jù)里保存類型指針,換句話說,查找對象的類的元數(shù)據(jù)信息不一定要通過對象本身)另外如果對象是一個數(shù)組,那么在對象頭中還必須有一塊來記錄數(shù)據(jù)的長度,因為虛擬機可以根據(jù)普通對象的元數(shù)據(jù)信息來確定對象的大小,但是從數(shù)組的元數(shù)據(jù)里無法確定數(shù)組的大小。
  • 實例數(shù)據(jù) (instance Data)
    對象真正存儲的有效信息,也是在程序代碼中定義的各種類型的字段內(nèi)容。無論是父類繼承的還是子類中定義的,都需要記錄起來。
    這部分的存儲順序會受到虛擬機分配策略參數(shù)(FieldsAllocationStyle)和字段在Java源碼中定義順序的影響。HotSpot虛擬機默認的分配策略為longs/doubles、ints、shorts/chars、bytes/booleans、oops(OrdinaryObjectPointers),從分配策略中可以看出,相同寬度的字段總是被分配到一起。在滿足這個前提條件的情況下,在父類中定義的變量會出現(xiàn)在子類之前。如果CompactFields參數(shù)值為true(默認為true),那么子類之中較窄的變量也可能會插入到父類變量的空隙之中。
  • 對齊填充(Padding)
    對齊填充并不是必然存在的,也沒有特別的含義,它僅僅起著占位符的作用。
    由于HotSpotVM的自動內(nèi)存管理系統(tǒng)要求對象起始地址必須是8字節(jié)的整數(shù)倍,換句話說,就是對象的大小必須是8字節(jié)的整數(shù)倍。而對象頭部分正好是8字節(jié)的倍數(shù)(1倍或者2倍),因此,當(dāng)對象實例數(shù)據(jù)部分沒有對齊時,就需要通過對齊填充來補全。

相關(guān)文章:
java虛擬機中對象的創(chuàng)建
java虛擬機中對象的內(nèi)存布局
java虛擬機中對象的定位

最后編輯于
?著作權(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ù)。

相關(guān)閱讀更多精彩內(nèi)容

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