一、对象头的结构(32位虚拟机)
1、普通对象
普通对象头占用64 bits ,其中Mark word占32 bits ,Klass Words 占32bits。Klass Words 可以理解为指针,指向类对象。Mark Word下面会详解。
2、数组对象
数组对象增加了4个字节的空间,用于存储数组长度。
二、Mark Word介绍
1、Mark Word结构
对象在不同情况下的结构会有所不同, 参考以下表格:
32位虚拟机Mark Word
64位虚拟机Mark Word
2、Mark Word 不同状态
1、Normal状态:此状态为普通状态,hashcode为对象的hashcode值 , age代表垃圾回收的分代年龄, biased_lock表示是否为偏向锁,最后两位代表加锁状态。
2、Biased状态:此状态为偏向锁状态,thread指向获得偏向锁的线程,后3位为101表示对象为偏向锁状态。
3、Lightweight Locked状态:轻量级锁状态,ptr_to_lock_record指向栈帧的锁记录。
4、Heavyweight Locked状态:重量级锁,ptr_to_heavyweight_monitor指向Monitor。
注意:
1、当开启偏向锁时(默认开启),创建一个对象,对象的Mark Word为偏向锁状态,偏向锁是默认延迟的,不会在程序启动时立即生效。
2、当禁用偏向锁时,创建的对象为普通状态,即使该对象被synchronized修饰,也不会变为偏向锁状态。
3、如果对象调用hashcode方法,会自动禁用偏向锁,是因为偏向锁的对象头中没办法存储hashcode。轻量级锁把Mark Word的值存放在栈帧中,重量级锁把Mark Word的值存放在Monitor中。
三、Monitor介绍
Monitor 是监视器的意思,在Java中被synchronized关键字修饰的对象头且为重量级锁时,会关联一个Monitor对象,Monitor有Owner、EntryList、WaitSet三个字段,分别表示Monitor的持有者线程(获得锁的线程)、阻塞队列、和等待队列。如下图:
上图的情况下,MarkWord状态应为heavyweight Locked,ptr_to_heavyweight_monitor占用30位指向Monitor对象。Thread-2为Monitor的持有者,因此Thread-2是获得锁的线程,其它争抢锁的线程进入阻塞队列中。