我们知道,Java对象头的结构如下:
内容 | 说明 | 备注 |
---|---|---|
Mark Word | 存储对象的Mark Word信息 | - |
Class Metadata Address | 存储指向对象存储类型的指针 | - |
Array Length | 数组的长度 | 只有数组对象有该属性 |
其中,在32位下,Mark Word的存储结构如下:
锁状态 | 23 bits | 2 bits | 4 bits | 1 bit | 2 bits |
---|---|---|---|---|---|
无锁状态 | identity hash code(首次调用) | 分代年龄 | 0 | 01 | |
偏向锁 | Thread ID | epoch | 分代年龄 | 1 | 01 |
轻量级锁 | 指向线程栈中Lock Record的指针 | 00 | |||
重量级锁 | 指向监视器(monitor)的指针 | 10 | |||
GC标记 | 0 | 11 |
在64位下,Mark Word的存储结构如下:
锁状态 | 25 bits | 31 bits | 1 bit | 4 bits | 1 bit | 2 bits | |
---|---|---|---|---|---|---|---|
无锁状态 | unused | identity hash code(首次调用) | unused | 分代年龄 | 0 | 01 | |
锁状态 | 54 bits | 2 bits | 1 bit | 4 bits | 1 bit | 2 bits | |
偏向锁 | Thread ID | epoch | unused | 分代年龄 | 1 | 01 | |
锁状态 | 62 bits | 2 bits | |||||
轻量级锁 | 指向线程栈中Lock Record的指针 | 00 | |||||
重量级锁 | 指向监视器(monitor)的指针 | 10 | |||||
GC标记 | 0 | 11 |
由此可知,在无锁状态下,Mark Word中可以存储对象的identity hash code值。当对象的hashCode()方法(非用户自定义)第一次被调用时,JVM会生成对应的identity hash code值(生成方式参见参考博客2),并将该值存储到Mark Word中。后续如果该对象的hashCode()方法再次被调用则不会再通过JVM进行计算得到,而是直接从Mark Word中获取。只有这样才能保证多次获取到的identity hash code的值是相同的(由参考博客2可知,以jdk8为例,JVM默认的计算identity hash code的方式得到的是一个随机数,因而我们必须要保证一个对象的identity hash code只能被底层JVM计算一次)。
我们还知道,对于轻量级锁,获取锁的线程栈帧中有锁记录(Lock Record)空间,用于存储Mark Word的拷贝,官方称之为Displaced Mark Word,该拷贝中可以包含identity hash code,所以轻量级锁可以和identity hash code共存;对于重量级锁,ObjectMonitor类里有字段可以记录非加锁状态下的mark word,其中也可以存储identity hash code的值,所以重量级锁也可以和identity hash code共存。
对于偏向锁,在线程获取偏向锁时,会用Thread ID和epoch值覆盖identity hash code所在的位置。如果一个对象的hashCode()方法已经被调用过一次之后,这个对象还能被设置偏向锁么?答案是不能。因为如果可以的化,那Mark Word中的identity hash code必然会被偏向线程Id给覆盖,这就会造成同一个对象前后两次调用hashCode()方法得到的结果不一致。
HotSpot VM的锁实现机制是:
1、https://www.cnblogs.com/twoheads/p/10150063.html jvm简介:偏向锁、轻量级锁和重量级锁
2、https://www.jianshu.com/p/be943b4958f4 Java Object.hashCode()返回的是对象内存地址吗?
3、https://www.zhihu.com/question/52116998/answer/133400077 当Java处在偏向锁、重量级锁状态时,hashcode值存储在哪
4、http://www.mamicode.com/info-detail-2601598.html 偏向锁浅析
5、https://blog.csdn.net/weixin_42213903/article/details/97044043 java 偏向锁
6、https://www.jianshu.com/p/6be2e37aca6f Java中hashCode的实现
7、https://www.jianshu.com/p/e74fe532e35e JVM知识整理