JVM:Hotspot虚拟机中的对象

在HotSpot虚拟机中,对象在内存中存储的布局可以被分为3个区域:对象头(Header)、实例数据(Instance data)和对齐填充(Padding).对象头包括两部分信息,第一部分存储自身的运行时数据,如哈希值、GC分代年龄、锁状态标志、线程持有的锁、偏向锁ID、偏向时间戳等,这部分数据的长度在32位和64位的虚拟机(未开启压缩指针)分别为32bit和64bit,官方称它为 Mark Word

存储内容 标志位 状态
对象哈希码、对象分代年龄 01 未锁定
指向锁记录的指针 00 轻量级锁定
指向重量级锁的指针 10 膨胀(重量级锁定)
空,不需要记录信息 11 GC标记
偏向ID、偏向时间戳、对象分代年龄 01 可偏向

查找对象的元数据信息不一定要经过对象本身。如果对象是一个数组,对象头必须有一块记录数组长度的数据,但是从数组的元数据中却无法确定大小。

实例数据部分是对象真正存储的有效信息,也就是在程序中所定义各种类型的字段内容。无论是父类继承下来的,还是在子类中定义的。这部分会影响虚拟机分配策略参数和字段在Java源码中定义顺序的影响。

对齐填充并不是必然存在的,没有特别含义,仅仅是占位符的作用。对象的的大小必须是8字节的整数倍,示例数据没有满足8字节的倍数,则会填充补全。

对象的访问定位
建立对象是为了使用对象,Java程序需要通过栈上的reference数据来操作堆上的具体对象。reference类型是一个对象的引用,并没有规定是用何种定位、访问堆中对象的具体位置,
这些取决于虚拟机的实现。目前主流的访问方式有句柄直接指针两种。

  1. 若是用句柄的话,Java堆中会划分一块内存来作为句柄池,reference中存储的是对象的句柄地址,而句柄中包含对象实例数据对象类型数据的具体地址信息。
  2. 若是用直接指针(开销小,速度相对较快),那么Java堆对象就必须考虑放置访问对象类型数据的相关信息,而reference中存储的就是对象地址

猜你喜欢

转载自www.cnblogs.com/magic-sea/p/11614370.html