Java对象头包含MarkWord、类型指针。
MarkWord 用于存储哈希码(HashCode)、GC分代年龄、锁状态标志位、线程持有的锁、偏向线程ID等信息。这部分数据长度在32位和64位虚拟机中的长度为32bit和64bit。

类型指针,即对象指向他的类元数据指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。另外,如果对象是一个 Java 数组,那么对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通 Java 对象的元数据信息来确定 Java 对象的大小,但是从数组的元数据中却无法确定数组的大小 。

接下来的实例数据(Instance Data)是对象真正存储的有效信息,也是代码中所定义的各种类型的字段信息。

第三部分对其填充并不是一定存在的,也没有特别的意义,只是起到了占位的作用。存在的原因是因为 HotSpot 虚拟机要求对象的起始地址必须是8的整数倍,换句话说就是对象的大小必须是8字节的整数倍,又因为对象头部分正好是8字节的整数倍,所以当实例数据部分没有对齐时,就需要通过对齐填充来补全。这样做是因为根据大量硬件测试,这种方式寻址速度更快.

下面是代码演示锁升级的过程,需要依赖

  <dependency>
      <groupId>org.openjdk.jol</groupId>
      <artifactId>jol-core</artifactId>
      <version>0.9</version>
  </dependency>
/**
* 无锁的对象,锁状态001
*/
@Test
public void t1() {
    Person person = new Person();
    System.out.println("无状态(001): "+ClassLayout.parseInstance(person).toPrintable());
}

结果:
无状态(001): AQS2022.Person 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)                           8d 79 01 20 (10001101 01111001 00000001 00100000) (536967565)
     12     4                int Person.age                                0
     16     4   java.lang.String Person.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
/**
     * 偏向锁对象,锁状态101
     */
    @Test
    public void t2() throws Exception {
        // jvm默认4s自动开启偏向锁,可通过-XX:BiasedLockingStartupDelay=0 取消延时
        // 可以通过-XX:-UseBiasedLocking 不要偏向锁,禁用后直接使用轻量锁(00)
        Thread.sleep(5000);
        Person person = new Person();
        for (int i = 0; i < 2; i++) {
            synchronized (person) {
                System.out.println("偏向锁(101)(带线程id): "+ClassLayout.parseInstance(person).toPrintable());
            }
        }
    }

结果:
偏向锁(101)(带线程id): AQS2022.Person object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           0d 68 ef 9b (00001101 01101000 11101111 10011011) (-1678809075)
      4     4                    (object header)                           6b 01 00 00 (01101011 00000001 00000000 00000000) (363)
      8     4                    (object header)                           8d 79 01 20 (10001101 01111001 00000001 00100000) (536967565)
     12     4                int Person.age                                0
     16     4   java.lang.String Person.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

    /**
     * 偏向锁升级为轻量级锁,锁状态00
     */
    @Test
    public void t3() throws Exception {
        Thread.sleep(5000);
        Person person = new Person();
        for (int i = 0; i < 2; i++) {
            synchronized (person) {
                System.out.println("偏向锁(101)(带线程id): "+ClassLayout.parseInstance(person).toPrintable());
            }
        }

        new Thread(()->{
            synchronized (person) {
                System.out.println("轻量级锁(00): "+ClassLayout.parseInstance(person).toPrintable());
                try {
                    System.out.println("睡眠3秒钟-------------------------");
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

结果:
偏向锁(101)(带线程id): AQS2022.Person object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           0d 68 b1 77 (00001101 01101000 10110001 01110111) (2008115213)
      4     4                    (object header)                           57 02 00 00 (01010111 00000010 00000000 00000000) (599)
      8     4                    (object header)                           8d 79 01 20 (10001101 01111001 00000001 00100000) (536967565)
     12     4                int Person.age                                0
     16     4   java.lang.String Person.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

偏向锁(101)(带线程id): AQS2022.Person object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           0d 68 b1 77 (00001101 01101000 10110001 01110111) (2008115213)
      4     4                    (object header)                           57 02 00 00 (01010111 00000010 00000000 00000000) (599)
      8     4                    (object header)                           8d 79 01 20 (10001101 01111001 00000001 00100000) (536967565)
     12     4                int Person.age                                0
     16     4   java.lang.String Person.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

轻量级锁(00): AQS2022.Person object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           18 f1 1f ac (00011000 11110001 00011111 10101100) (-1407192808)
      4     4                    (object header)                           83 00 00 00 (10000011 00000000 00000000 00000000) (131)
      8     4                    (object header)                           8d 79 01 20 (10001101 01111001 00000001 00100000) (536967565)
     12     4                int Person.age                                0
     16     4   java.lang.String Person.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

睡眠3秒钟-------------------------
    /**
     * 偏向锁101 -->升级为轻量级锁00 -->升级为重量级锁10
     * @throws Exception
     */
    @Test
    public void t4() throws Exception {
        Thread.sleep(5000);
        Person person = new Person();
        for (int i = 0; i < 2; i++) {
            synchronized (person) {
                System.out.println("偏向锁(101)(带线程id): "+ClassLayout.parseInstance(person).toPrintable());
            }
        }

        new Thread(()->{
            synchronized (person) {
                System.out.println("轻量级锁(00): "+ClassLayout.parseInstance(person).toPrintable());
                try {
                    System.out.println("睡眠3秒钟-------------------------");
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        // 在前面线程持有锁的情况下,争抢锁
        AtomicBoolean isGetLock = new AtomicBoolean(false);
        while (!isGetLock.get()) {
            new Thread(()->{
                synchronized (person) {
                    System.out.println("重量级锁(10): "+ClassLayout.parseInstance(person).toPrintable());
                    isGetLock.compareAndSet(false,true);
                }
            }).start();
            Thread.sleep(1000);
        }
    }
结果:
偏向锁(101)(带线程id): AQS2022.Person object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           0d 60 85 9e (00001101 01100000 10000101 10011110) (-1635426291)
      4     4                    (object header)                           e7 01 00 00 (11100111 00000001 00000000 00000000) (487)
      8     4                    (object header)                           8d 79 01 20 (10001101 01111001 00000001 00100000) (536967565)
     12     4                int Person.age                                0
     16     4   java.lang.String Person.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

偏向锁(101)(带线程id): AQS2022.Person object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           0d 60 85 9e (00001101 01100000 10000101 10011110) (-1635426291)
      4     4                    (object header)                           e7 01 00 00 (11100111 00000001 00000000 00000000) (487)
      8     4                    (object header)                           8d 79 01 20 (10001101 01111001 00000001 00100000) (536967565)
     12     4                int Person.age                                0
     16     4   java.lang.String Person.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

轻量级锁(00): AQS2022.Person object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           1a 5e 6e b6 (00011010 01011110 01101110 10110110) (-1234280934)
      4     4                    (object header)                           e7 01 00 00 (11100111 00000001 00000000 00000000) (487)
      8     4                    (object header)                           8d 79 01 20 (10001101 01111001 00000001 00100000) (536967565)
     12     4                int Person.age                                0
     16     4   java.lang.String Person.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

睡眠3秒钟-------------------------
重量级锁(10): AQS2022.Person object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           1a 5e 6e b6 (00011010 01011110 01101110 10110110) (-1234280934)
      4     4                    (object header)                           e7 01 00 00 (11100111 00000001 00000000 00000000) (487)
      8     4                    (object header)                           8d 79 01 20 (10001101 01111001 00000001 00100000) (536967565)
     12     4                int Person.age                                0
     16     4   java.lang.String Person.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

重量级锁(10): AQS2022.Person object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           1a 5e 6e b6 (00011010 01011110 01101110 10110110) (-1234280934)
      4     4                    (object header)                           e7 01 00 00 (11100111 00000001 00000000 00000000) (487)
      8     4                    (object header)                           8d 79 01 20 (10001101 01111001 00000001 00100000) (536967565)
     12     4                int Person.age                                0
     16     4   java.lang.String Person.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

重量级锁(10): AQS2022.Person object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           1a 5e 6e b6 (00011010 01011110 01101110 10110110) (-1234280934)
      4     4                    (object header)                           e7 01 00 00 (11100111 00000001 00000000 00000000) (487)
      8     4                    (object header)                           8d 79 01 20 (10001101 01111001 00000001 00100000) (536967565)
     12     4                int Person.age                                0
     16     4   java.lang.String Person.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
posted on 2022-02-19 20:06  被杜撰的风  阅读(139)  评论(0)    收藏  举报