java对象结构
HotSpot虚拟机 markOop.cpp 中的 C++ 代码注释片段,描述了 64bits 下 mark-word 的存储状态,也就是如上图结构示意。
markOop.cpp 源码地址: jdk8/hotspot/file/vm/oops/markOop.hpp
HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header)
、实例数据(Instance Data)
和对齐填充(Padding)
。
- mark-word:对象标记字段占4个字节,用于存储一些列的标记位,比如:哈希值、轻量级锁的标记位,偏向锁标记位、分代年龄等。
- Klass Pointer:Class对象的类型指针,Jdk1.8默认开启指针压缩后为4字节,关闭指针压缩(
-XX:-UseCompressedOops
)后,长度为8字节。其指向的位置是对象对应的Class对象(其对应的元数据对象)的内存地址。 - 对象实际数据:包括对象的所有成员变量,大小由各个成员变量决定,比如:byte占1个字节8比特位、int占4个字节32比特位。
- 对齐:最后这段空间补全并非必须,仅仅为了起到占位符的作用。由于HotSpot虚拟机的内存管理系统要求对象起始地址必须是8字节的整数倍,所以对象头正好是8字节的倍数。因此当对象实例数据部分没有对齐的话,就需要通过对齐填充来补全。
另外,在mark-word锁类型标记中,无锁,偏向锁,轻量锁,重量锁,以及GC标记,5种类中没法用2比特标记(2比特最终有4种组合00
、01
、10
、11
),所以无锁、偏向锁,前又占了一位偏向锁标记。最终:001为无锁、101为偏向锁。
1 | <!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core --> |
1 | public class A { |
1 | com.yzw.juc.markWord.A@5cad8086 十六进制哈希:5cad8086 |
- 运行结果
如上图: markWord 占8字节 Klass Point占4字节 实际的对象数据占8字节 最后四个字节用于填充对齐
如上图: 对象的头部也存放了hash,只不过这个哈希值是倒过来的
关于倒过来的问题是大小端存储导致的
- Big-Endian:高位字节存放于内存的低地址端,低位字节存放于内存的高地址端
- Little-Endian:低位字节存放于内存的低地址端,高位字节存放于内存的高地址端
markWord结构