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
浙公网安备 33010602011771号