文末有彩蛋?。。。。。?/p>
對象中的數(shù)據(jù)
前兩篇,我們講到了Java對象的類加載,Java對象的初始化操作。本篇,我們來繼續(xù)學(xué)習(xí)Java對象,看看Java對象在內(nèi)存中如何布局,看看Java對象中由哪些數(shù)據(jù)構(gòu)成,以及教給大家如何測量一個對象的大小。
HotSpot虛擬機(jī)下,一個對象在內(nèi)存中包含了3大區(qū)域,分別為:對象頭(Header)、實(shí)例數(shù)據(jù)(Instance Data)和對齊填充(Padding)。
對象頭(Header)
對象頭,顧名思義就是對象的頭部。如果按照一個團(tuán)隊(duì)來看,對象頭就好比團(tuán)隊(duì)中的領(lǐng)導(dǎo)。對于一個團(tuán)隊(duì)來說,領(lǐng)導(dǎo)至關(guān)重要。對于一個對象來說,對象頭不可或缺。
在計(jì)算機(jī)領(lǐng)域中,很多知識概念都有頭的存在,例如:Http請求頭。
在HotSpot虛擬機(jī)中,對象頭包括兩部分:Mark Word和類型指針。
那么,什么是Mark Word呢?什么是類型指針呢?
(1)Mark Word
Mark Word直譯為標(biāo)記字段,主要用于存儲對象自身的運(yùn)行時(shí)數(shù)據(jù),如哈希碼(HashCode)、GC分代年齡、鎖狀態(tài)標(biāo)志、線程持有的鎖、偏向線程ID、偏向時(shí)間戳等。
在不同的運(yùn)行環(huán)境中,所占用內(nèi)存的大小也不盡相同。在32位的機(jī)器中,Mark Word大小為32bit,4字節(jié)。在64位機(jī)器中,Mark Word大小為64bit,也就是8字節(jié)。
考慮到虛擬機(jī)的存儲空間,Mark Word被設(shè)計(jì)成一個非固定的數(shù)據(jù)結(jié)構(gòu)以便在最小的內(nèi)存中存儲更多的有用信息。
對于Mark Work來說,在不同場景下存儲著不一樣的信息。例如:在32位計(jì)算機(jī)中,如果一個對象處于未鎖定(沒有被加鎖)狀態(tài)下,那么該對象的Mard Word大小為32bit,其中25bit用戶存儲對象哈希碼,4bit用于存儲對象分代年齡,2bit用于存儲鎖標(biāo)志位,1bit固定為0。
而其他場景如下:
| 場景 | 存儲內(nèi)容 | 鎖標(biāo)志位 |
|---|---|---|
| 未加鎖 | 對象哈希碼、對象分代年齡 | 01 |
| 輕量級鎖定 | 指向鎖記錄的指針 | 00 |
| 重量級鎖定 | 指向重量級鎖的指針 | 10 |
| GC標(biāo)記 | 不需要記錄任何信息 | 11 |
| 偏向鎖 | 偏向線程ID、偏向時(shí)間戳、對象分代年齡 | 01 |
可以看出,在不同場景下,Mark Word中存儲的數(shù)據(jù)是不一樣的。要注意的是,當(dāng)一個對象從未加鎖狀態(tài)轉(zhuǎn)向其他狀態(tài)時(shí),原有的存儲內(nèi)容并不會丟失、被覆蓋,而是在當(dāng)前線程的棧幀中建立一個名為鎖記錄(Lock Record)的空間,用于存儲鎖對象目前的Mark Word的拷貝。
對于想要了解鎖機(jī)制的朋友,首先需要對Mark Word有所了解,鎖的實(shí)現(xiàn)離不開Mark Word。關(guān)于鎖的內(nèi)容,會在后面的多線程中進(jìn)行講解。
(2)類型指針
類型指針:對象指向其類元數(shù)據(jù)的指針,虛擬機(jī)通過這個指針確定該對象是哪個類的實(shí)例。
值得注意的是,如果對象是一個Java數(shù)組,那在對象頭中還必須有一塊區(qū)域用于記錄數(shù)組的長度,因?yàn)樘摂M機(jī)可以通過普通Java對象的元數(shù)據(jù)信息確定Java對象的大小,但是從數(shù)組的元數(shù)據(jù)中無法確定數(shù)組的大小。
實(shí)例數(shù)據(jù)(Instance Data)
實(shí)例數(shù)據(jù)部分,存儲著對象真正的有效信息,也就是代碼中定義的各種類型字段內(nèi)容。無論是父類繼承下來的,還是子類中自己定義的,都會在實(shí)例數(shù)據(jù)中保存起來。
實(shí)例數(shù)據(jù)的保存順序,跟代碼中定義的順序有較大的關(guān)系,通常情況下父類中定義的變量會排在子類之前。
原生類型(primitive type)的內(nèi)存占用如下:
| 原生類型 | 占用內(nèi)存大小(字節(jié)) |
|---|---|
| boolean | 1 |
| byte | 1 |
| short | 2 |
| char | 2 |
| int | 4 |
| float | 4 |
| long | 8 |
| double | 8 |
| reference | 4/8 |
對齊填充(Padding)
對齊填充,主要起到補(bǔ)全的作用。在HotSpot VM中,要求對象的大小必須是8字節(jié)的整數(shù)倍,當(dāng)對象頭+實(shí)例數(shù)據(jù)的大小不滿足此要求時(shí),就用到對齊填充來進(jìn)行補(bǔ)全。

京東購買鏈接:可伸縮服務(wù)架構(gòu)-框架與中間件