探究java對象頭


       探究java對象頭

研究java對象頭,我這里先截取Hotspot中關於對象頭的描述,本文研究基於64-bit HotSpot VM

文件路徑 openjdk-jdk8u-jdk8u\hotspot\src\share\vm\oops\markOop.hpp

//  32 bits:
//  --------
//             hash:25 ------------>| age:4    biased_lock:1 lock:2 (normal object)
//             JavaThread*:23 epoch:2 age:4    biased_lock:1 lock:2 (biased object)
//             size:32 ------------------------------------------>| (CMS free block)
//             PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)
//
//  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)
//
//  unused:25 hash:31 -->| cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && normal object)
//  JavaThread*:54 epoch:2 cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && biased object)
//  narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)
//  unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)

一:java對象組成 : 對象頭(mark word 和 klass Pointer,如果是數組,包含數組長度)、實例化數據、對齊填充

借助openJdk中的工具類JOL來分析java對象布局

maven的pom.xml中添加依賴
<dependency> <groupId>org.openjdk.jol</groupId> <artifactId>jol-core</artifactId> <version>0.9</version> </dependency>
Test1:
public
class A { boolean flag = false ; } ------------------------------------------------------------ public class Current{ public static void main(String[] args) { A obj = new A(); A[] b = new A[10]; System.out.println(VM.current().details());
System.out.println(ClassLayout.parseInstance(obj).toPrintable());
System.out.println(ClassLayout.parseInstance(b).toPrintable()); } }

運行結果:

# Running 64-bit HotSpot VM.
# Using compressed oop with 0-bit shift.
# Using compressed klass with 3-bit shift.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

 
         

com.yew.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) 43 a1 f9 27 (01000011 10100001 11111001 00100111) (670671171)
12 1 boolean A.flag false
13 3 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 3 bytes external = 3 bytes total

[Lcom.yew.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) 81 a1 f9 27 (10000001 10100001 11111001 00100111) (670671233)
12 4 (object header) 0a 00 00 00 (00001010 00000000 00000000 00000000) (10)
16 40 com.yew.A A;.<elements> N/A
Instance size: 56 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

 Test1分析:普通對象總共16B,對象頭占用12B,另外4B(64位虛擬機上對象的大小必須是8的倍數)為對齊填充字節。

 

Hotspot中的重要術語:
mark word The first word of every object header. Usually a set of bitfields including synchronization state and identity hash code. May also be a pointer (with characteristic low bit encoding) to synchronization related information. During GC, may contain GC state bits. 每個對象頭的第一個word。通常是一組位字段,包括同步狀態和標識哈希值。也可以是指向同步相關信息的指針(具有特征性的低位編碼)。在GC期間,可以包含GC狀態位
klass pointer The second word of every object header. Points to another object (a metaobject) which describes the layout and behavior of the original object. For Java objects, the "klass" contains a C++ style "vtable". klass word為對象頭的第二個word,主要指向對象的元數據;
object header Common structure at the beginning of every GC-managed heap object. (Every oop points to an object header.) Includes fundamental information about the heap object's layout, type, GC state, synchronization state, and identity hash code. Consists of two words. In arrays it is immediately followed by a length field. Note that both Java objects and VM-internal objects have a common object header format.
對象頭由兩個word組成,每個GC管理堆對象的開頭都存在這樣一個公共結構。(每個oop都指向一個對象頭)包含有關堆對象的布局、類型、GC狀態、同步狀態和哈希值的基本信息。在數組中,后面緊接着是一個長度字段。注意Java對象和VM內部對象都有一個通用的對象頭格式。

二:java對象頭

64位對象頭由Mark Word、klass pointer兩部分組成,如果對象是數組,則還要加上數組長度,即三部分組成。

Mark Word由64位8個字節組成,klass pointer由64位8個字節組成,但我們使用的64位 JVM會默認使用選項 +UseCompressedOops 開啟指針壓縮,將指針壓縮至32位。即上面截圖中的klass pointer為4個字節32位。這里重點描述下Mark Word部分。

Mark Word的64位,不同的位表示的意思不一樣,具體如下所示:

|--------------------------------------------------------------------------------------------------------------|
|                                              Object Header (128 bits)                                        |
|--------------------------------------------------------------------------------------------------------------|
|                        Mark Word (64 bits)                                    |      Klass Word (64 bits)    |默認開啟指針壓縮       
|--------------------------------------------------------------------------------------------------------------|
|unused:25|identity_hashcode:31(56) | unused:1 | age:4 | biased_lock:1 | lock:2 |     OOP to metadata object   |  無鎖
|----------------------------------------------------------------------|--------|------------------------------|
|  thread:54 |         epoch:2      | unused:1 | age:4 | biased_lock:1 | lock:2 |     OOP to metadata object   |  偏向鎖
|----------------------------------------------------------------------|--------|------------------------------|
|                     ptr_to_lock_record:62                            | lock:2 |     OOP to metadata object   |  輕量鎖
|----------------------------------------------------------------------|--------|------------------------------|
|                     ptr_to_heavyweight_monitor:62                    | lock:2 |     OOP to metadata object   |  重量鎖
|----------------------------------------------------------------------|--------|------------------------------|
|                                                                      | lock:2 |     OOP to metadata object   |    GC
|--------------------------------------------------------------------------------------------------------------|
對象在無鎖的情況下,前56位為對象的hashCode值,下面為驗證代碼Test2:
public
class Current{ public static void main(String[] args) throws Exception { A obj = new A(); out.println("before hash"); out.println(ClassLayout.parseInstance(obj).toPrintable()); out.println("JVM hash==="+Integer.toHexString(obj.hashCode())); out.println("after hash"); countHash(obj); out.println(ClassLayout.parseInstance(obj).toPrintable()); } public static void countHash(Object obj) throws Exception { Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); Unsafe unsafe = (Unsafe) field.get(null); long hashCode = 0; for (long index = 7; index > 0; index--) { hashCode |= (unsafe.getByte(obj, index) & 0xFF) << ((index-1) * 8); } String code = Long.toHexString(hashCode); out.println("util 0x===="+code); } }

執行結果:

before hash
com.yew.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) 43 21 ed 27 (01000011 00100001 11101101 00100111) (669851971)
12 1 boolean A.flag false
13 3 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 3 bytes external = 3 bytes total

JVM hash===368102c8
after hash
util 0x====368102c8

很明顯:此處得到的值與對象的hashCode值相等
com.yew.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 c8 02 81 (00000001 11001000 00000010 10000001) (-2130524159)
4 4 (object header) 36 00 00 00 (00110110 00000000 00000000 00000000) (54)
8 4 (object header) 43 21 ed 27 (01000011 00100001 11101101 00100111) (669851971)
12 1 boolean A.flag false
13 3 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 3 bytes external = 3 bytes total

Test2分析:因為對象字節采用小端存儲,所以無鎖狀態2-7字節存放的是對象的Hashcode值,那么第一個字節8位存放的是分代年齡、偏向鎖信息,和對象狀態

2.1 無鎖

public class NoLock {
public static void main(String[] args) {
A a = new A();
System.out.println(ClassLayout.parseInstance(a).toPrintable());
a.hashCode();
System.out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
執行結果:

com.yew.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) 43 21 f6 27 (01000011 00100001 11110110 00100111) (670441795)
12 1 boolean A.flag false
13 3 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 3 bytes external = 3 bytes total

com.yew.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 c8 02 81 (00000001 11001000 00000010 10000001) (-2130524159)
4 4 (object header) 36 00 00 00 (00110110 00000000 00000000 00000000) (54)
8 4 (object header) 43 21 f6 27 (01000011 00100001 11110110 00100111) (670441795)
12 1 boolean A.flag false
13 3 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 3 bytes external = 3 bytes total

分析結果:當一個對象才new且調用了hashcode方法后(如果不調用hashcode方法,那么存放hashcode的31位全部為0),正常情況下處於無鎖狀態,無鎖狀態時,Mark Word的64位分別為:前25位未使用,接下來的31位為對象的hashcode,接下來的1位未使用,接下來的4位表示對象的GC年齡,接下來的一位為偏向鎖狀態,最后2位表示鎖狀態,如上圖所示。

2.2 偏向鎖

偏向鎖:1.保證線程安全;2.不存在資源競爭
public class BiasedLock {
public static void main(String[] args) /**throws InterruptedException**/ {
// Thread.sleep(4000);
// Thread.sleep(5000);
A a = new A();
System.out.println("before lock");
System.out.println(ClassLayout.parseInstance(a).toPrintable());
synchronized (a){
System.out.println("locking...........");
System.out.println(ClassLayout.parseInstance(a).toPrintable());
}
System.out.println("after lock");
System.out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
執行結果如下:

before lock
com.yew.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) 43 c1 fa 27 (01000011 11000001 11111010 00100111) (670744899)
12 1 boolean A.flag false
13 3 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 3 bytes external = 3 bytes total

 
         

locking...........
com.yew.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) e8 f0 6c 02 (11101000 11110000 01101100 00000010) (40693992)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 43 c1 fa 27 (01000011 11000001 11111010 00100111) (670744899)
12 1 boolean A.flag false
13 3 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 3 bytes external = 3 bytes total

 
         

after lock
com.yew.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) 43 c1 fa 27 (01000011 11000001 11111010 00100111) (670744899)
12 1 boolean A.flag false
13 3 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 3 bytes external = 3 bytes total

測試分析:根據執行結果分析,對象a並沒有成為偏向鎖,而是由 無鎖-輕量鎖-無鎖。因為上述案例僅有一個線程調用synchronized,預期為偏向鎖,但是實際運行與預期不符,根據查詢資料發現,虛擬機在啟動的時候會延遲開啟偏向鎖(時間約為4300ms),便於測試,可以通過設置JVM參數關閉偏向鎖的延遲加載。IDEA設置方式:Run-->Edit Configurations->VM Options -XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0,再次運行可得結果。

before lock
com.yew.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) 43 e1 fd 27 (01000011 11100001 11111101 00100111) (670949699)
12 1 boolean A.flag false
13 3 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 3 bytes external = 3 bytes total

此時占用 thread 和 epoch 的 位置的均為0,說明當前偏向鎖並沒有偏向任何線程。此時這個偏向鎖正處於可偏向狀態,准備好進行偏向了!你也可以理解為此時的偏向鎖是一個特殊狀態的無鎖

locking...........
com.yew.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 05 f0 27 02 (00000101 11110000 00100111 00000010) (36171781)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 43 e1 fd 27 (01000011 11100001 11111101 00100111) (670949699)
12 1 boolean A.flag false
13 3 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 3 bytes external = 3 bytes total

synchronized(a),對a加鎖后,對象a偏向了某個線程,所以2-8位表示的是線程的ID標識,所以顯然此時對象a已經成為偏向鎖。

after lock
com.yew.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 05 f0 27 02 (00000101 11110000 00100111 00000010) (36171781)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 43 e1 fd 27 (01000011 11100001 11111101 00100111) (670949699)
12 1 boolean A.flag false
13 3 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 3 bytes external = 3 bytes total

退出同步代碼塊,依然是偏向鎖

睡眠5s或者關閉偏向鎖延遲加載時 偏向鎖(可偏向)--->偏向鎖(偏向線程)--->偏向鎖

2.3 輕量鎖

public class LightLock {
    public static void main(String[] args) {
        A a = new A();
        synchronized (a){
            System.out.println("locking......");
            System.out.println(ClassLayout.parseInstance(a).toPrintable());
        }
    }
}

locking......
com.yew.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 28 f4 ef 02 (00101000 11110100 11101111 00000010) (49280040)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 43 e1 f0 27 (01000011 11100001 11110000 00100111) (670097731)
12 1 boolean A.flag false
13 3 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 3 bytes external = 3 bytes total

結果分析:JVM默認開啟偏向鎖延遲加載,所以當使用synchronized給對象加鎖時,該對象會膨脹為輕量鎖。

2.4 重量鎖

重量鎖:當存在線程競爭同一把鎖時,就會由輕量鎖膨脹為重量級鎖;
public
class WeightLock { static A a = new A(); public static void main(String[] args) throws InterruptedException { System.out.println("before lock"); System.out.println(ClassLayout.parseInstance(a).toPrintable());//無鎖 new Thread(new Runnable(){ @Override public void run() { synchronized (a){ System.out.println("once locking"); System.out.println(ClassLayout.parseInstance(a).toPrintable());//輕量鎖 try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("thread release"); } } }).start(); Thread.sleep(1000); System.out.println("main printLock"); System.out.println(ClassLayout.parseInstance(a).toPrintable());//輕量鎖 synchronized (a){ System.out.println("second locking"); System.out.println(ClassLayout.parseInstance(a).toPrintable());//重量鎖 } System.out.println("after locking"); System.out.println(ClassLayout.parseInstance(a).toPrintable());//重量鎖 System.gc(); System.out.println("after gc"); System.out.println(ClassLayout.parseInstance(a).toPrintable());//gc標記 } }
執行結果:

before lock
com.yew.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 07 1e (00011000 00001010 00000111 00011110) (503777816)
12 4 int A.i 0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

 
         

once locking
com.yew.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) b0 f1 e2 0b (10110000 11110001 11100010 00001011) (199422384)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 18 0a 07 1e (00011000 00001010 00000111 00011110) (503777816)
12 4 int A.i 0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

 
         

main printLock
com.yew.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) b0 f1 e2 0b (10110000 11110001 11100010 00001011) (199422384)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 18 0a 07 1e (00011000 00001010 00000111 00011110) (503777816)
12 4 int A.i 0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

 
         

thread release
second locking
com.yew.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) ca 9f ac 08 (11001010 10011111 10101100 00001000) (145530826)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 18 0a 07 1e (00011000 00001010 00000111 00011110) (503777816)
12 4 int A.i 0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

 
         

after locking
com.yew.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) ca 9f ac 08 (11001010 10011111 10101100 00001000) (145530826)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 18 0a 07 1e (00011000 00001010 00000111 00011110) (503777816)
12 4 int A.i 0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

 
         

after gc
com.yew.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 09 00 00 00 (00001001 00000000 00000000 00000000) (9)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 18 0a 07 1e (00011000 00001010 00000111 00011110) (503777816)
12 4 int A.i 0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

Biased_lock(1bits)

Lock(2bits)

description

0

01

無鎖

1

01

偏向鎖

0

00

輕量鎖

0

10

重量鎖

0

01

無鎖--GC標記

三:偏向鎖/輕量級鎖/重量級鎖

上述三種鎖是指鎖的狀態,並且是針對Synchronized。通過引入鎖升級的機制來實現高效Synchronized。鎖的狀態是通過對象監視器在對象頭中的字段來表明的。

偏向鎖:一段同步代碼一直被一個線程所訪問,那么該線程會自動獲取鎖。降低獲取鎖的代價。

輕量級鎖:當鎖是偏向鎖的時候,被另一個線程所訪問,偏向鎖就會升級為輕量級鎖,其他線程會通過自旋的形式嘗試獲取鎖,不會阻塞,提高性能。

重量級鎖:當鎖為輕量級鎖的時候,另一個線程雖然是自旋,但自旋不會一直持續下去,當自旋一定次數的時候,還沒有獲取到鎖,就會進入阻塞,該鎖膨脹為重量級鎖。重量級鎖會讓它申請的線程進入阻塞,性能降低。

自旋鎖:自旋鎖是指嘗試獲取鎖的線程不會立即阻塞,而是采用循環的方式去嘗試獲取鎖,這樣的好處是減少線程上下文切換的消耗,缺點是循環會消耗CPU。

三:性能比較

3.1 偏向鎖和輕量鎖的性能對比

//偏向鎖 關閉偏向鎖延遲加載
//VM Options -XX:BiasedLockingStartupDelay=0
@Test
public void testBiasedLock(){
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000000 ; i++) {
synchronized (a){
count++;
}
}
long end = System.currentTimeMillis();
System.out.println("耗時為:"+(end-start)+"ms");
System.out.println(count);
}

//輕量鎖
@Test
public void testLightLock(){
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000000 ; i++) {
synchronized (a){
count++;
}
}
long end = System.currentTimeMillis();
System.out.println("耗時為:"+(end-start)+"ms");//36742ms
System.out.println(count);
}
//重量鎖
@Test
public void testWeightLock(){
A a = new A();
long start = System.currentTimeMillis();
for (int i = 0; i < 2; i++) {
new Thread(a::parse, "t" + i).start();
}
System.out.println(Thread.activeCount());
while (Thread.activeCount()>2){
Thread.yield();
}
long end = System.currentTimeMillis();
System.out.println("耗時為:"+(end-start)+"ms");//50727ms
System.out.println(a.getI());
}

鎖的狀態

偏向鎖(B)

輕量鎖(L)

重量鎖(W)

性能比較

耗時

4424ms

36742ms

50727ms

B>L>W

四:其他

4.1 對象計算過哈希后無法重新偏向

//關閉偏向鎖延遲加載 -XX:BiasedLockingStartupDelay=0
public class HashLockTest {
static A a = new A();
public static void main(String[] args) {
System.out.println("before hash");
System.out.println(ClassLayout.parseInstance(a).toPrintable());//可偏向
a.hashCode();//計算hashcode
synchronized (a){
System.out.println("after hash");
System.out.println(ClassLayout.parseInstance(a).toPrintable());//輕量鎖
}
System.out.println(ClassLayout.parseInstance(a).toPrintable());//無鎖
}
}

4.2 調用wait方法--->重量鎖

public class WaitLockTest {
   static A a = new A();
    public static void main(String[] args) throws InterruptedException {
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (a){
                    System.out.println("before wait");
                    System.out.println(ClassLayout.parseInstance(a).toPrintable());//輕量鎖
                    try {
                        a.wait();
                    } catch (InterruptedException e) {
                    }
                    System.out.println("after wait");
                    System.out.println(ClassLayout.parseInstance(a).toPrintable());
                }
            }
        }).start();
        Thread.sleep(7000);
        synchronized (a){
            a.notify();
        }
    }
}
執行結果:

before wait
com.yew.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 90 f6 04 0b (10010000 11110110 00000100 00001011) (184874640)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 43 e1 ed 27 (01000011 11100001 11101101 00100111) (669901123)
12 4 int A.i 0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

 
         

after wait
com.yew.A object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 9a 95 86 08 (10011010 10010101 10000110 00001000) (143037850)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 43 e1 ed 27 (01000011 11100001 11101101 00100111) (669901123)
12 4 int A.i 0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM