为了账号安全,请及时绑定邮箱和手机立即绑定

深入理解JVM读书笔记(3)-对象的布局和访问

标签:
Java JVM

1. 对象的内存布局

在HotSpot虚拟机中,对象在内存中存储的布局可以分为3个区域:对象头(Header),实例数据(Instance Data)和对齐填充(Padding)。

1.1 对象头

对象头包含2部分的信息:第一部分用于存储对象自身的运行时数据,如哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳等。这部分数据的长度在32位和64位的虚拟机中分别为32bit64bit,官方称它为Mark Word

Mark Word会复用自己的存储空间。例如,在32位的HotSpot虚拟机中,如果对象处于未被锁定的状态下,则25bit用于存储对象哈希码,4bit用于存储对象分代年龄,2bit用于存储锁标志位,1bit固定为0。其状态下对象的存储内容如下:

图片描述

JVM一般是这样使用锁和Mark Word的:

  1. 当没有被当成锁时,这就是一个普通的对象,Mark Word记录对象的HashCode,锁标志位是01,是否偏向锁那一位是0。

  2. 当对象被当做同步锁并有一个线程A抢到了锁时,锁标志位还是01,但是否偏向锁那一位改成1,前23bit记录抢到锁的线程id,表示进入偏向锁状态。

  3. 当线程A再次试图来获得锁时,JVM发现同步锁对象的标志位是01,是否偏向锁是1,也就是偏向状态,Mark Word中记录的线程id就是线程A自己的id,表示线程A已经获得了这个偏向锁,可以执行同步锁的代码。

  4. 当线程B试图获得这个锁时,JVM发现同步锁处于偏向状态,但是Mark Word中的线程id记录的不是B,那么线程B会先用CAS操作试图获得锁,这里的获得锁操作是有可能成功的,因为线程A一般不会自动释放偏向锁。如果抢锁成功,就把Mark Word里的线程id改为线程B的id,代表线程B获得了这个偏向锁,可以执行同步锁代码。如果抢锁失败,则继续执行步骤5。

  5. 偏向锁状态抢锁失败,代表当前锁有一定的竞争,偏向锁将升级为轻量级锁。JVM会在当前线程的线程栈中开辟一块单独的空间,里面保存指向对象锁Mark Word的指针,同时在对象锁Mark Word中保存指向这片空间的指针。上述两个保存操作都是CAS操作,如果保存成功,代表线程抢到了同步锁,就把Mark Word中的锁标志位改成00,可以执行同步锁代码。如果保存失败,表示抢锁失败,竞争太激烈,继续执行步骤6。

  6. 轻量级锁抢锁失败,JVM会使用自旋锁,自旋锁不是一个锁状态,只是代表不断的重试,尝试抢锁。从JDK1.7开始,自旋锁默认启用,自旋次数由JVM决定。如果抢锁成功则执行同步锁代码,如果失败则继续执行步骤7。

  7. 自旋锁重试之后如果抢锁依然失败,同步锁会升级至重量级锁,锁标志位改为10。在这个状态下,未抢到锁的线程都会被阻塞。

对象头的另一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。如果对象是一个Java数组,那么对象头重还必须有一块用于记录数组长度的数据。该数据在32位和64位JVM中长度都是32bit。

1.2 实例数据

实例数据部分是对象真正存储的有效信息。这部分的存储顺序会受到虚拟机分配策略参数和字段在Java源码中定义顺序的影响。HotSpot的分配策略中,相同宽度的字段总是被分配在一起,在这个前提下,在父类中定义的变量会出现在子类之前。

1.3 填充字段

这个字段不是必然存在的,仅仅是占位符。HotSpot虚拟机要求对象起始地址必须是8字节的整数倍。对象头部分是8字节的整数倍。所以,当对象实例数据的部分没有对齐时候,就需要通过对齐填充来补全。

2. 对象的访问定位

对于reference类型的对象的访问,目前主流的访问方式有使用句柄和直接指针两种。

  • 如果使用句柄,Java堆中将会划分出来一块内存作为句柄池,reference中存储的就是对象的句柄地址
    图片描述

  • 直接指针访问,reference中存储的直接就是对象地址。

图片描述

对比

使用句柄进行访问最大的好处就是reference中存储的是稳定的句柄地址,在对象被移动时智慧改变句柄中的实例数据指针,而reference本身不需要修改。

使用直接指针的好处是速度更快,节省了一次指针定位的事件开销,HotSpot虚拟机使用的是直接指针的方式进行对象的访问。

3. 引用

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
1万
获赞与收藏
1426

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消