对象的结构
对象由对象头、实例数据、填充数据三部分组成,三个部分内存加起来必须要求是8个倍数个字节
1、Header(对象头,默认12个字节)
- 自身运行时数据(Mark Word)包括哈希值、GC分代年龄、是否开启偏向锁、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等
- 类型指针(klass) 即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例
- 数组长度(只有数组才有)
补充:
对象头由2个部分组成:_mark(8字节)+oop指针。
oop指针和引用对象在开启压缩普通对象指针(-XX:+UseCompressedOops)时大小为4字节,关闭压缩普通对象指针(-XX:+UseCompressedOops)时为8字节。UseCompressedOops默认是开启的,只有虚拟机内存达到32G以上,4个字节已经无法满足寻址需求时,才需要关闭该参数
2、实例数据
类里面定义的变量,byte/short/int/long/float/double/boolean/char还有引用数据类型,实例数据就是类定义属性变量的字节加起来总和
对于引用数据类型的大小如上对对象头中指针一样,不同位数JVM会有区别。在 32 位的 JVM 上,一个对象引用占用 4 个字节;在 64 位上,占用 8 个字节,开启指针压缩情况下占用4个字节。
对于基本数据类型
3、填充数据(只有存在填充数据时才有,否则为0字节)
因为JVM要求对象结构内存大小是8字节的倍数,所以要对齐填充数据的作用就是填充 对象头+实例数据 不足8个倍数那个部分。如对象头12个字节,实例数据只有一个byte变量,则填充数据必须填充3个字节(12+1+3=16,是8的倍数),它仅仅起着占位符的作用
对象的结构图
Mark World图