[JAVA基礎(chǔ)] - JVM對象內(nèi)存布局及鎖的標記位

一、對象布局

1、對象頭

1)存儲對象自身的運行時數(shù)據(jù)
hash碼、GC分代年齡、鎖狀態(tài)標志、線程持有的鎖、偏向線程ID、偏向時間戳等。占位32/64位虛擬機分別占32/64個比特,官方稱"Mark Word"

2)類型指針
指向?qū)ο蟮脑獢?shù)據(jù),如果是數(shù)組,還會存儲數(shù)組長度。

2、實例數(shù)據(jù)
3、對齊填充

要求對象是8的整數(shù)倍,對象頭已經(jīng)是8位的整數(shù)倍,只填充實例數(shù)據(jù)即可。

二、Object o = new Object()內(nèi)存占用情況

占用16個字節(jié)
對象頭12個字節(jié),對齊填充4個字節(jié),共16個

使用ClassLayout進行查看內(nèi)存布局
maven

<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.9</version>
</dependency>
Object o = new Object();
System.out.println(ClassLayout.parseInstance(o).toPrintable());

輸出結(jié)果

java.lang.Object 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)                           e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

三、查看鎖的標記位

1652873201(1).png

鎖升級過程
1、無鎖狀態(tài)(001)
2、無鎖 ->偏向鎖 : 給普通對象加個synchronized,初始就是偏向鎖(101)
3、偏向鎖 -> 自旋鎖(輕量級鎖 00),JVM發(fā)現(xiàn)有第二個線程去競爭該鎖,變成自旋鎖(輕量級鎖 00)
4、自旋鎖 -> 重量級鎖 : 當JVM發(fā)現(xiàn)線程競爭激烈的時候,就把自旋鎖升級為重量級鎖。判斷標準有兩個,一個是自旋超過10次,另一個是wait的線程個數(shù)超過CPU的一半。

1、未鎖定=>輕量級鎖定
    public static void main(String[] args) {
        Object o = new Object();
        System.out.println(ClassLayout.parseInstance(o).toPrintable());

        synchronized (o){
            System.out.println(ClassLayout.parseInstance(o).toPrintable());
        }
    }
1652873487(1).png
2、輕量級鎖=>重量級鎖
    @SneakyThrows
    public static void main(String[] args) {
        Object o = new Object();
        System.out.println("new ---" + ClassLayout.parseInstance(o).toPrintable());

        new Thread(() -> {
            synchronized (o) {
                System.out.println("Thread 1 -- " + ClassLayout.parseInstance(o).toPrintable());
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        Thread.sleep(1000);

        new Thread(() -> {
            synchronized (o) {
                System.out.println("Thread 2 -- " + ClassLayout.parseInstance(o).toPrintable());
            }
        }).start();
    }
image.png
?著作權(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)容