對(duì)象是什么
JAVA是一個(gè)面向?qū)ο蟮恼Z(yǔ)言,在Java中可以使用new關(guān)鍵字來產(chǎn)生一個(gè)對(duì)象,但這個(gè)對(duì)象到底是什么,應(yīng)該具有哪些屬性?
首先跟我們自己先想下,Java對(duì)象已經(jīng)有以下幾個(gè)屬性:
- 屬于哪個(gè)類
- 有哪些字段和類型
- 對(duì)象的值 ….
在HotSpot虛擬機(jī)中,真實(shí)的Java對(duì)象是分成三個(gè)部分:
- 對(duì)象頭
- 對(duì)象的值
- 對(duì)象的填充字節(jié) (在JVM中,要求對(duì)象占用內(nèi)存的大小應(yīng)該是8bit的倍數(shù),這個(gè)信息是用來補(bǔ)齊8bit的,無(wú)其他作用)
對(duì)象頭
對(duì)象頭是Java中對(duì)象都具有的屬性,是jvm在編譯和運(yùn)行階段讀取的信息。對(duì)象頭包含三個(gè)部分:
- mark word
- 指針向類的指針
- 數(shù)組的長(zhǎng)度(只有數(shù)組的對(duì)象用到)
這3個(gè)中最復(fù)雜的是MarkWord,MarkWord用于存儲(chǔ)對(duì)象自身的運(yùn)行時(shí)數(shù)據(jù), 如哈希碼(HashCode)、GC分代年齡、鎖狀態(tài)標(biāo)志、線程持有的鎖、偏向線程ID、偏向時(shí)間戳等等。在32bit的環(huán)境中,Java頭存儲(chǔ)的信息如下
對(duì)象頭的應(yīng)用
偏向鎖
在HotSpot的虛擬機(jī)中,當(dāng)一個(gè)線程訪問同步塊并嘗試獲取鎖時(shí),會(huì)在對(duì)象頭和棧幀中的記錄里存儲(chǔ)鎖的偏向的線程ID,以后該線程進(jìn)入和退出同步塊的代碼時(shí)候,不需要再進(jìn)行加鎖 ,只需要檢測(cè)下MarkWord中的是否是當(dāng)前線程的偏向鎖。如果成功,則說明已經(jīng)獲得了鎖,如果檢測(cè)不成功,就再進(jìn)行加鎖。
輕量級(jí)鎖
線程在執(zhí)行同步塊之前,JVM會(huì)現(xiàn)在當(dāng)前的線程的棧幀中創(chuàng)建用于存儲(chǔ)鎖記錄的空間,并肩對(duì)象頭的MarkWord復(fù)制到鎖的記錄中,然后線程嘗試將對(duì)象頭MarkWord替換為指向鎖記錄的指針,如果不成功,說明鎖存在競(jìng)爭(zhēng),當(dāng)前線程開始進(jìn)行盲等來獲取鎖。