Java 对象的内存布局(对象头)

引语

在学习 synchronize 时,遇到了关于对象头的知识,特地写篇文章记录一下

对象的内存布局

对象在堆内存中的存储布局可以分为三部分:

  1. 对象头(Header)
  2. 实例数据(Instance Data)
  3. 对齐填充(Padding)

学习工具

我们可以通过 jol 的 jar 包,查看对象内存布局

maven 依赖如下:

<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.15</version>
</dependency>

我们创建一个类 MyLock ,类中只包含一个 int 类型的属性

MyLock lock = new MyLock();
System.out.println(ClassLayout.parseInstance(lock).toPrintable());

打印信息如下:

cn.arc.java.synchronize.MyLock object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000001 (non-biasable; age: 0)
  8   4        (object header: class)    0x2000c143
 12   4    int MyLock.value              0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

其中 OFF 为偏移量,SZ 为大小(两者单位为字节)

对象头

在 openjdk 文档中对对象头进行说明

hotspot 文档

Common structure at the beginning of every GC-managed heap object. (Every oop points to an object header.) Includes fundamental information about the heap object’s layout, type, GC state, synchronization state, and identity hash code. Consists of two words. In arrays it is immediately followed by a length field. Note that both Java objects and VM-internal objects have a common object header format.

重点有二:

  1. 我们可以看到对象头包括两个 word ,至于 word 是什么,在以下文章中有所解释,简单说就是总线中数据传输单位, 64 位系统下一个 word 就是 64 位长度

    word 的解释

  2. 数组对象中紧跟着这两个 word 后就是数组长度

这两个 word 分别是 Mark Word 和 klass pointer (class pointer)

我们可以在之前的打印信息中看到,一个对象确实存在 mark word 和 class pointer 两个属性,但是我们可以看到 class pointer 的大小为 4 字节,我的机器为 64 位,照理说应该为 8 字节,这是因为 jvm 默认开启了指针压缩技术

OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000001 (non-biasable; age: 0)
  8   4        (object header: class)    0x2000c143

下面是一个数组对象的打印信息,可以看到存在一个数组长度信息,(我们可以说长度是对象头信息也可以不是,不过这不重要)

OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000001 (non-biasable; age: 0)
  8   4        (object header: class)    0x2000cda4
 12   4        (array length)            2

Mark Word

The first word of every object header. Usually a set of bitfields including synchronization state and identity hash code. May also be a pointer (with characteristic low bit encoding) to synchronization related information. During GC, may contain GC state bits.

包括锁状态(或执行锁信息的指针),hashcode,GC 期间可能有 GC 状态

我们也可以在 hotspot 源代码中 markOop.hpp 文件,找到关于 Mark Word 的存放的信息的相关注释(hotspot :源码下载

我们只看 normal object ,可以看到有 hashcode , age(GC 分代年龄),biased_lock(偏向锁标记), lock(锁状态标记),还存在未使用的位

//  64 bits:
//  --------
//  unused:25 hash:31 -->| unused:1   age:4    biased_lock:1 lock:2 (normal object)
//  JavaThread*:54 epoch:2 unused:1   age:4    biased_lock:1 lock:2 (biased object)
//  PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
//  size:64 ----------------------------------------------------->| (CMS free block)

klass pointer(class pointer)

The second word of every object header. Points to another object (a metaobject) which describes the layout and behavior of the original object. For Java objects, the “klass” contains a C++ style “vtable”.

指向对象的类型元数据的指针,对象的类型元数据是存放在存放在方法区的(这里我没法跟踪到)

实例数据

实例数据就是对象中有效的数据,即我们在类中定义的字段,以及父类中继承的字段,注意类静态变量是不存放在实例对象中的,存放的顺序受虚拟机分配策略参数(-XX:FieldsAllocationStyle参数)和定义顺序决定;

对齐填充

不一定存在,仅起到占位符的作用,HotSpot 内存管理系统要求对象起始地址为 8 的整数倍,所以当对象的大小不到 8 的倍数需要填充

测试一下:

创建一个只有一个 int 和 boolean 的对象,打印对象信息可以看到存在一个 object alignment gap (对象对齐间隙),即对齐填充

cn.arc.java.synchronize.MyLock2 object internals:
OFF  SZ      TYPE DESCRIPTION               VALUE
  0   8           (object header: mark)     0x0000000000000001 (non-biasable; age: 0)
  8   4           (object header: class)    0x2000cde0
 12   4       int MyLock2.value             0
 16   1   boolean MyLock2.value2            false
 17   7           (object alignment gap)    
Instance size: 24 bytes
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值