Java对象头及锁

2021-08-18  本文已影响0人  晚歌歌

对象组成

对象头

Java对象头由以下三部分组成

Mark Word

Mark Word记录了对象和锁有关的信息,当这个对象被synchronized关键字当成同步锁时,围绕这个锁的一系列操作都和Mark Word有关。
Mark Word在32位JVM中的长度是32bit,在64位JVM中长度是64bit
Mark Word在不同的锁状态下存储的内容不同,在32位JVM中是这么存的:


image.png

其中无锁和偏向锁的锁标志位都是01,只是在前面的1bit区分了这是无锁状态还是偏向锁状态。
JDK1.6以后的版本在处理同步锁时存在锁升级的概念,JVM对于同步锁的处理是从偏向锁开始的,随着竞争越来越激烈,处理方式从偏向锁升级到轻量级锁,最终升级到重量级锁。

可以看出无锁情况下,前面位数保存的是对象的HashCode,那么偏向锁、轻量级锁、重量级锁如何获取对象的HashCode?

HashCode生成规则:在无锁状态下,Mark Word 中可以存储对象的 identity hash code 值。当对象的 hashCode() 方法(非用户自定义)第一次被调用时,JVM 会生成对应的 identity hash code 值,并将该值存储到 Mark Word 中。后续如果该对象的hashCode() 方法再次被调用则不会再通过 JVM 进行计算得到,而是直接从 Mark Word 中获取。只有这样才能保证多次获取到的 identity hash code 的值是相同的

HotSpot VM 的锁实现机制是:

指向类的指针

该指针在32位JVM中的长度是32bit,在64位JVM中长度是64bit。
Java对象的类数据保存在方法区。

数组长度

只有数组对象保存了这部分数据。
该数据在32位和64位JVM中长度都是32bit。

压缩指针

-XX:+UseCompressedOops,64位JVM才有且1.6之后默认开启,作用是将对象头中的类指针压缩至32位

原理

对于32位的CPU和操作系统来说,32位的指针可以表示
2的32次方 = 4Gbit 个地址,而每个地址占用的内存空间为1个byte(因为CPU运算位数是32位,所以每次都是按byte读取),因此32操作系统支持的最大内存位4Gbit * 8 = 4GB

对于64位的JVM来说,64位的指针理论上可以表示的地址无限大
指针压缩后变为32位指针,如上所述理论上只能表示 4Gbit 个地址,支持4GB的内存,但是假如每个地址占用的内存空间改为8个byte,那么就能够支持 4GB * 8 = 32GB的内存了,JVM就是这样运用8字节对齐填充的特性通过映射的方式达到内存扩充的效果

如果堆大小大于 32 GB,压缩指针就不能用了

上一篇 下一篇

猜你喜欢

热点阅读