使用JOL研究Java對(duì)象的布局以及對(duì)象頭信息:
-- 對(duì)象里面的屬性是逐個(gè)添加
public class A {
????private String name ;
????private int age;
????private boolean flag;
????private List<String> list;
}
public class JOLExample3 {
????public static void main(String[] args) {
????????A a = new A();
????????out.println(VM.current().details());
????????out.println(ClassLayout.parseInstance(a).toPrintable());
????}
}
運(yùn)行結(jié)果:
-- 對(duì)象A沒(méi)有屬性
sync.demo.A object internals:
OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE
??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001 00000000 00000000 00000000) (1)
??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)
??????8?????4????????(object header)???????????????????????????18 0a 1f 18 (00011000 00001010 00011111 00011000) (404687384)
?????12?????4????????(loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
-- 對(duì)象A有一個(gè)String類(lèi)型的name屬性
sync.demo.A object internals:
OFFSET??SIZE???????????????TYPE DESCRIPTION???????????????????????????????VALUE
??????0?????4????????????????????(object header)???????????????????????????01 00 00 00 (00000001 00000000 00000000 00000000) (1)
??????4?????4????????????????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)
??????8?????4????????????????????(object header)???????????????????????????18 0a c7 17 (00011000 00001010 11000111 00010111) (398920216)
?????12?????4???java.lang.String A.name????????????????????????????????????null
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
-- 對(duì)象A有一個(gè)String類(lèi)型的name屬性富弦,和一個(gè)int類(lèi)型的age屬性
sync.demo.A object internals:
OFFSET??SIZE???????????????TYPE DESCRIPTION???????????????????????????????VALUE
??????0?????4????????????????????(object header)???????????????????????????01 00 00 00 (00000001 00000000 00000000 00000000) (1)
??????4?????4????????????????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)
??????8?????4????????????????????(object header)???????????????????????????18 0a d7 17 (00011000 00001010 11010111 00010111) (399968792)
?????12?????4????????????????int A.age?????????????????????????????????????0
?????16?????4???java.lang.String A.name????????????????????????????????????null
?????20?????4????????????????????(loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
-- 對(duì)象A有一個(gè)String類(lèi)型的name屬性母蛛,和一個(gè)int類(lèi)型的age屬性,一個(gè)boolean類(lèi)型的flag屬性
sync.demo.A object internals:
OFFSET??SIZE???????????????TYPE DESCRIPTION???????????????????????????????VALUE
??????0?????4????????????????????(object header)???????????????????????????01 00 00 00 (00000001 00000000 00000000 00000000) (1)
??????4?????4????????????????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)
??????8?????4????????????????????(object header)???????????????????????????18 0a d6 17 (00011000 00001010 11010110 00010111) (399903256)
?????12?????4????????????????int A.age?????????????????????????????????????0
?????16?????1????????????boolean A.flag????????????????????????????????????false
?????17?????3????????????????????(alignment/padding gap)??????????????????
?????20?????4???java.lang.String A.name????????????????????????????????????null
Instance size: 24 bytes
Space losses: 3 bytes internal + 0 bytes external = 3 bytes total
-- 對(duì)象A有一個(gè)String類(lèi)型的name屬性刹淌,和一個(gè)int類(lèi)型的age屬性饶氏,一個(gè)boolean類(lèi)型的flag屬性,一個(gè)List<String>屬性
sync.demo.A object internals:
OFFSET??SIZE???????????????TYPE DESCRIPTION???????????????????????????????VALUE
??????0?????4????????????????????(object header)???????????????????????????01 00 00 00 (00000001 00000000 00000000 00000000) (1)
??????4?????4????????????????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)
??????8?????4????????????????????(object header)???????????????????????????18 0a bf 17 (00011000 00001010 10111111 00010111) (398395928)
?????12?????4????????????????int A.age?????????????????????????????????????0
?????16?????1????????????boolean A.flag????????????????????????????????????false
?????17?????3????????????????????(alignment/padding gap)??????????????????
?????20?????4???java.lang.String A.name????????????????????????????????????null
?????24?????4?????java.util.List A.list????????????????????????????????????null
?????28?????4????????????????????(loss due to the next object alignment)
Instance size: 32 bytes
Space losses: 3 bytes internal + 4 bytes external = 7 bytes total
總結(jié):
從上面的對(duì)象布局中有勾,隨著對(duì)象中的屬性越來(lái)越多疹启,占用的字節(jié)就越來(lái)越大,但是始終是8的倍數(shù)蔼卡,不夠就進(jìn)行填充喊崖;
但是objectheader 始終占用12byte;
總結(jié):
Instance size: 56 bytes 對(duì)象的大泄统选荤懂;都是8的倍數(shù),64位虛擬機(jī)對(duì)象的大小必須是8的倍數(shù)塘砸;
object header:
從上面的結(jié)果可以分析出每個(gè)對(duì)象頭的大小占12byte节仿;這12byte分別包含兩個(gè)word,mark_word 和 klass_word掉蔬;
mark_word:占8byte廊宪,mark_word是我們重點(diǎn)研究的;下面詳細(xì)說(shuō)明眉踱;
klass_word:剩下的4byte是 klass_word挤忙,用于只想對(duì)象的元數(shù)據(jù);比如class模板谈喳;
(loss due to the next object alignment):用于對(duì)其填充册烈,當(dāng)對(duì)象大小不是8的倍數(shù)的時(shí)候,就使用對(duì)象填充使其對(duì)齊婿禽;
官方文檔:
Every object (except array) in memory has 2 machine word header.?The first one is called mark word and the second one is klass word. Btw arrays have extra 32 bit word filled with array’s length.
Mark word?stores identity hashcode, bits used for garbage collection, bits used for locking. To find out more check out the source from OpenJDK.
Klass word?stores ordinary object pointer (oop) to class metadata, which describes the object’s layout, methods, and other type information. To find out more check out the metadata source from OpenJDK.
下面來(lái)看下mark_word中詳細(xì)描述了什么:
// 64 bits:
// --------
// unused:25 hash:31 -->| unused:1 age:4 biased_lock:1 lock:2 (normal object)
// JavaThread*:54 epoch:2 unused:1 age:4 biased_lock:1 lock:2 (biased object)
// PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
// size:64 ----------------------------------------------------->| (CMS free block)
以上是JVM源碼注釋
解釋一下其中的名詞:
unused:沒(méi)有被使用
identity_hashcode:用于存儲(chǔ)對(duì)象的hashCode:
【
identity_hashcode?-identity hashcode of the object which is assigned lazily. If System.identityHashCode(obj) is called, it is calculated and written into the object header. When object is locked the identity hashcode value is moved into the monitor object
】
age:GC分代年齡赏僧;
【
age?-?number of garbage collections the object has survived. It is incremented every time an object is copied within the young generation. When the age field reaches the value of max-tenuring-threshold, the object is promoted to the old generation
】
biased_lock:偏向鎖狀態(tài);
【
biased_lock?-?contains 1 if the biased locking is enabled for the class. 0 if the biased locking is disabled for the class. To find out more on biased locking check out my previous
】
lock:對(duì)象狀態(tài)扭倾;分為無(wú)鎖淀零,輕量級(jí)鎖,重量級(jí)鎖膛壹,GC標(biāo)記驾中;
【
lock?-the lock state of the object. 00 - Lightweight Locked, 01 - Unlocked or Biased, 10 - Heavyweight Locked, 11 - Marked for Garbage Collection. To find out more on locking/synchronization check out synchronization post
】
無(wú)鎖狀態(tài)的mark_word:
unused:25:無(wú)鎖狀態(tài)下mark wod中前25位沒(méi)有被使用;
identity_hashcode:31:用于存儲(chǔ)對(duì)象hashCode模聋,包括前面的25個(gè)都是用來(lái)存儲(chǔ)對(duì)象的hashCode肩民,所以mark word前56為是用于存儲(chǔ)無(wú)鎖對(duì)象的hashCode;下面會(huì)驗(yàn)證一下java對(duì)象的hashCode是不是存儲(chǔ)在這里面链方;
unused:1:無(wú)鎖狀態(tài)下沒(méi)有使用持痰;
age:4:GC分代年齡;對(duì)象幸存的垃圾收集數(shù)量祟蚀。 每次在年輕一代中復(fù)制對(duì)象時(shí)工窍,它都會(huì)遞增割卖。 當(dāng)年齡字段達(dá)到max-tenuring-threshold的值時(shí),該對(duì)象將被提升為舊一代患雏;
biased_lock:1:偏向鎖標(biāo)識(shí)鹏溯;
lock:2:對(duì)象狀態(tài);
來(lái)看看無(wú)鎖狀態(tài)下的mark_word:
先驗(yàn)證一下前56為是不是用于存儲(chǔ)對(duì)象的hashCode:
public class JOLExample {
????public static void main(String[] args) {
????????A a = new A();
????????out.println("計(jì)算hashcode之前纵苛。剿涮。。");
????????out.println(ClassLayout.parseInstance(a).toPrintable());
????????out.println("計(jì)算對(duì)象a的hashcode攻人,10進(jìn)制:"+a.hashCode());
????????out.println("計(jì)算hashcode之后取试。。怀吻。");
????????out.println(ClassLayout.parseInstance(a).toPrintable());
????}
}
打印如下:
計(jì)算hashcode之前瞬浓。。蓬坡。
sync.demo.A object internals:
OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE
0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)
??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000?00000000 00000000 00000000) (0)
??????8?????4????????(object header)???????????????????????????18 0a cd 17 (00011000 00001010 11001101 00010111) (399313432)
?????12?????4????????(loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
計(jì)算對(duì)象a的hashcode猿棉,10進(jìn)制:1213415012
計(jì)算hashcode之后。屑咳。萨赁。
sync.demo.A object internals:
OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE
0?????4????????(object header)???????????????????????????01 64 3e 53 (00000001?01100100 00111110 01010011) (1396597761)
??????4?????4????????(object header)???????????????????????????48 00 00 00 (01001000?00000000 00000000 00000000) (72)
??????8?????4????????(object header)???????????????????????????18 0a cd 17 (00011000 00001010 11001101 00010111) (399313432)
?????12?????4????????(loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
通過(guò)進(jìn)制轉(zhuǎn)換工具將對(duì)象的10進(jìn)制hashcode轉(zhuǎn)換成二進(jìn)制:
? ?十六進(jìn)制?? ??? ??? ???? ??? ??? ??? ??? ??? ?二進(jìn)制
1213415012:?? ??? ?01001000 01010011 00111110 01100100
對(duì)象頭中標(biāo)紅的hashcode:
01100100 00111110 01010011?01001000
兩個(gè)進(jìn)行對(duì)比一下:
我們打印出來(lái)并進(jìn)行二進(jìn)制轉(zhuǎn)換的hashCode:??01001000 01010011 00111110 01100100
JOL打印出來(lái)的object header中的hashCoxe:? ??01100100 00111110 01010011?01001000
是不是發(fā)現(xiàn)不一樣?那是因?yàn)閣indows操作系統(tǒng)是小端存儲(chǔ)兆龙,是反過(guò)來(lái)的杖爽;我們來(lái)翻轉(zhuǎn)一下:
我們打印出來(lái)并進(jìn)行二進(jìn)制轉(zhuǎn)換的hashCode:??01001000 01010011 00111110 01100100
JOL打印出來(lái)的object header中的hashCoxe:? ??01001000?01010011?00111110?01100100
一樣的吧,說(shuō)明官方文檔中說(shuō)是對(duì)的紫皇;
最后來(lái)研究一下mark word中最后8bit慰安,也是最終的8bit;
unused:1 age:4 biased_lock:1 lock:2
分別存儲(chǔ)GC分代年齡聪铺,偏向鎖標(biāo)識(shí)化焕,對(duì)象狀態(tài);見(jiàn)下圖铃剔;
JOL打印中的最后8bit:?00000001
? ? ? ? 0? ? ? ? ? ? ? ? ? ?0000? ? ? ? ? ? ? 0? ? ? ? ? ? ? ?01
沒(méi)有被使用? ? ? GC分代年齡? ? 偏向標(biāo)識(shí)? ? 對(duì)象狀態(tài)
我們著重分析一下最后三位撒桨,其中最后兩位是用于標(biāo)識(shí)對(duì)象狀態(tài),也就是鎖狀態(tài)键兜,Java中的對(duì)象狀態(tài)有:無(wú)鎖凤类,偏向鎖,輕量鎖蝶押,重量鎖踱蠢,GC標(biāo)識(shí)五種狀態(tài)火欧;
那么最后兩位最多組合只能表示4中狀態(tài):00棋电,01茎截,10,11赶盔,JVM怎么表示五種狀態(tài)呢胜臊?
答案就是JVM把偏向鎖和無(wú)鎖表示為同一種狀態(tài)隶校,隨后通過(guò)偏向標(biāo)識(shí),來(lái)區(qū)分偏向鎖和無(wú)鎖,當(dāng)偏向鎖的時(shí)候规伐,偏向標(biāo)識(shí)是1,對(duì)象狀態(tài)是01疚脐,下面會(huì)具體分析溪烤;
因?yàn)樯厦娲a中并沒(méi)有對(duì)對(duì)象A進(jìn)行加鎖操作,所以打印出來(lái)的是無(wú)鎖狀態(tài)闷叉,可以判定擦俐,在無(wú)鎖時(shí)的mark_word中對(duì)象頭的偏向標(biāo)識(shí)是不可偏向0,且對(duì)象狀態(tài)是01握侧,代表無(wú)鎖蚯瞧;
public class JOLExample {
????static A a ;
????public static void main(String[] args) throws InterruptedException {
????????a = new A();
????????out.println("對(duì)象A加鎖之前。品擎。埋合。"); //預(yù)期應(yīng)該是無(wú)鎖
????????out.println(ClassLayout.parseInstance(a).toPrintable());
????????sync();
????????out.println("對(duì)象A加鎖之后。萄传。甚颂。"); //預(yù)期應(yīng)該是偏向鎖
????????out.println(ClassLayout.parseInstance(a).toPrintable());
????}
????public static void sync(){
????????synchronized (a){
????????????out.println("對(duì)象A加鎖中 ing 。盲再。西设。"); //預(yù)期應(yīng)該是無(wú)鎖
????????????out.println(ClassLayout.parseInstance(a).toPrintable());
????????}
????}
}
結(jié)果:
對(duì)象A加鎖之前。答朋。贷揽。
sync.demo.A object internals:
OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE
??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)
??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)
??????8?????4????????(object header)???????????????????????????18 0a f0 17 (00011000 00001010 11110000 00010111) (401607192)
?????12?????4????????(loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
對(duì)象A加鎖中 ing 。梦碗。禽绪。
sync.demo.A object internals:
OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE
??????0?????4????????(object header)???????????????????????????30 f1 91 03 (00110000?11110001 10010001 00000011) (59896112)
??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)
??????8?????4????????(object header)???????????????????????????18 0a f0 17 (00011000 00001010 11110000 00010111) (401607192)
?????12?????4????????(loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
對(duì)象A加鎖之后。洪规。印屁。
sync.demo.A object internals:
OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE
??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)
??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)
??????8?????4????????(object header)???????????????????????????18 0a f0 17 (00011000 00001010 11110000 00010111) (401607192)
?????12?????4????????(loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
從上面的打印結(jié)果我們可以知道,上面執(zhí)行的代碼斩例,并沒(méi)有資源競(jìng)爭(zhēng)雄人,至始至終都是main線程在執(zhí)行,在Java1.6之前,JVM中synchronized關(guān)鍵字的實(shí)現(xiàn)方式是調(diào)用操作系統(tǒng)底層的pthread_mutex_t? 函數(shù)實(shí)現(xiàn)加鎖础钠,而1.6之后進(jìn)行了優(yōu)化恰力,在沒(méi)有資源競(jìng)爭(zhēng)的情況下,JVM的加鎖應(yīng)該是偏向鎖旗吁,但是從結(jié)果中看踩萎,肯定不是偏向鎖,因?yàn)槠驑?biāo)識(shí)是0很钓,這里的000是一個(gè)輕量鎖香府,因?yàn)闆](méi)有資源競(jìng)爭(zhēng),肯定不是重量級(jí)鎖码倦,那么怎樣才能看到偏向鎖呢企孩?為什么這里默認(rèn)就從無(wú)鎖升級(jí)為輕量鎖了呢?看下一一段代碼
public class JOLExample1 {
????static A a ;
????public static void main(String[] args) throws InterruptedException {
????????//延遲5秒
????????Thread.sleep(5000);
????????a = new A();
????????out.println("對(duì)象A加鎖之前袁稽。柠硕。。");
????????out.println(ClassLayout.parseInstance(a).toPrintable());
????????sync();
????????out.println("對(duì)象A加鎖之后运提。蝗柔。。");
????????out.println(ClassLayout.parseInstance(a).toPrintable());
????}
????public static void sync(){
????????synchronized (a){
????????????out.println("對(duì)象A加鎖中 ing 民泵。癣丧。。");
????????????out.println(ClassLayout.parseInstance(a).toPrintable());
????????}
????}
}
運(yùn)行結(jié)果:
對(duì)象A加鎖之前栈妆。胁编。。
sync.demo.A object internals:
OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE
??????0?????4????????(object header)???????????????????????????05 00 00 00 (00000101?00000000 00000000 00000000) (5)
??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)
??????8?????4????????(object header)???????????????????????????18 0a c1 17 (00011000 00001010 11000001 00010111) (398527000)
?????12?????4????????(loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
對(duì)象A加鎖中 ing 鳞尔。嬉橙。。
sync.demo.A object internals:
OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE
??????0?????4????????(object header)???????????????????????????05 f8 c6 02 (00000101?11111000 11000110 00000010) (46594053)
??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)
??????8?????4????????(object header)???????????????????????????18 0a c1 17 (00011000 00001010 11000001 00010111) (398527000)
?????12?????4????????(loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
對(duì)象A加鎖之后寥假。市框。。
sync.demo.A object internals:
OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE
??????0?????4????????(object header)???????????????????????????05 f8 c6 02 (00000101?11111000 11000110 00000010) (46594053)
??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)
??????8?????4????????(object header)???????????????????????????18 0a c1 17 (00011000 00001010 11000001 00010111) (398527000)
?????12?????4????????(loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
打印結(jié)果出來(lái)了糕韧,有沒(méi)有被嚇到枫振,101,偏向鎖萤彩;
兩個(gè)疑問(wèn):
1.為什么延遲5秒粪滤,執(zhí)行同步代碼塊時(shí)是偏向鎖?
2.為什么對(duì)象一開(kāi)始就已經(jīng)是偏向鎖雀扶,不應(yīng)該是無(wú)鎖嗎杖小?
再看一個(gè)運(yùn)行結(jié)果:在JVM執(zhí)行參數(shù)中加入-XX:BiasedLockingStartupDelay=0,一會(huì)在解釋這個(gè)參數(shù)有什么作用
運(yùn)行結(jié)果:
對(duì)象A加鎖之前。予权。县踢。
sync.demo.A object internals:
OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE
??????0?????4????????(object header)???????????????????????????05 00 00 00 (00000101?00000000 00000000 00000000) (5)
??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)
??????8?????4????????(object header)???????????????????????????18 0a dd 17 (00011000 00001010 11011101 00010111) (400362008)
?????12?????4????????(loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
對(duì)象A加鎖中 ing 。伟件。。
sync.demo.A object internals:
OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE
??????0?????4????????(object header)???????????????????????????05 f8 c9 02 (00000101?11111000 11001001 00000010) (46790661)
??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)
??????8?????4????????(object header)???????????????????????????18 0a dd 17 (00011000 00001010 11011101 00010111) (400362008)
?????12?????4????????(loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
對(duì)象A加鎖之后议经。斧账。。
sync.demo.A object internals:
OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE
??????0?????4????????(object header)???????????????????????????05 f8 c9 02 (00000101?11111000 11001001 00000010) (46790661)
??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)
??????8?????4????????(object header)???????????????????????????18 0a dd 17 (00011000 00001010 11011101 00010111) (400362008)
?????12?????4????????(loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
上面的代碼關(guān)閉睡眠煞肾,加上了-XX:BiasedLockingStartupDelay=0這個(gè)運(yùn)行參數(shù)咧织,為什么對(duì)象一開(kāi)始就是偏向鎖了呢?前面例子不是在沒(méi)有睡眠之前是無(wú)鎖的呀籍救,為什么現(xiàn)在一上來(lái)就變成偏向鎖习绢?
-XX:BiasedLockingStartupDelay=0 就是這個(gè)參數(shù)的原因,這個(gè)參數(shù)是禁止偏向鎖延遲蝙昙,因?yàn)镴VM默認(rèn)是延遲開(kāi)啟偏向鎖的闪萄,時(shí)間大概是4秒左右,那JVM為什么要延遲開(kāi)啟偏向鎖呢奇颠?那是因?yàn)榘苋ィ贘VM啟動(dòng)的時(shí)候,JVM認(rèn)為在JVM啟動(dòng)的時(shí)候烈拒,JVM的運(yùn)行程序中的同步代碼都是存在資源競(jìng)爭(zhēng)的圆裕,沒(méi)有必要開(kāi)啟偏向鎖的必要,等我JVM啟動(dòng)完了荆几,在開(kāi)啟偏向鎖供用戶使用吓妆。所以就出現(xiàn)了前面的差異;
總結(jié)一下Java Object header:
Java對(duì)象頭一共占12byte吨铸,其中mark word占8byte行拢,klass占4byte;
鎖狀態(tài):
001:無(wú)鎖
101:偏向鎖
000:輕量級(jí)鎖
010:重量級(jí)鎖