参考当Java处在偏向锁、重量级锁状态时,hashcode值存储在哪?

对象头.png

由上图可以看出来,HotSpot VM 为了优化空间,复用了对象头的一部分空间,不免产生一个疑问:当对象头处于锁定状态时,其对象哈希码、分代年龄、偏向模式等数据又存放在哪里了呢?

偏向锁

  • 当一个对象已经计算过identity hash code,它就无法进入偏向锁状态
  • 当一个对象当前正处于偏向锁状态,并且需要计算其identity hash code的话,则它的偏向锁会被撤销,并且锁会膨胀为重量锁

在偏向锁中,哈希码和线程ID复用同一块空间,HotSpot VM是以实际上只有很少对象会计算identity hash code为前提来进行了优化,所以对象没有计算哈希码的时候可以使用偏向锁,一但计算之后,空间被占用则不能再使用偏向锁了。

轻量锁

虚拟机首先将在当前线程的栈帧中建立一个名为锁记录(Lock Record)的空间,用于存储锁对象目前的Mark Word的拷贝(官方为这份拷贝加了一个Displaced前缀,即Displaced Mark Word)。
然后,虚拟机将使用CAS操作尝试把对象的Mark Word更新为指向Lock Record的指针。

轻量锁加锁过程.png

如图所示,Mark Word的值都被存在了栈帧里的Lock Record里,自然可以获取到其哈希码、分代年龄等。

重量锁

重量锁的实现中,ObjectMonitor类里有字段可以记录非加锁状态下的Mark Word,其中可以存储identity hash code的值。或者简单说就是重量锁可以存下identity hash code。
ObjectMonitor是虚拟机中的一个C++类。