JAVA 对象大小

写在前面

看了网上很多描述,其实已经写的很详细了,但是自己没有实践过总是觉得有点蒙蒙的


概念

Java对象的内存布局:对象头(Header),实例数据(Instance Data)和对齐填充(Padding)
虚拟机的对象头包括两部分信息,第一部分用于存储对象自身的运行时数据,如hashCode、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。这部分数据的长度在32位和64的虚拟机(未开启指针压缩)中分别为4B和8B,官方称之为”Mark Word”。
对象的另一部分是类型指针(kclass),即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是那个类的实例。另外如果对象是一个Java数组,那再对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通Java对象的元数据信息确定Java对象的大小,但是从数组的元数据中却无法确定数组的大小。
对象头在32位系统上占用8B,64位系统上占16B。 无论是32位系统还是64位系统,对象都采用8字节对齐。Java在64位模式下开启指针压缩,比32位模式下,头部会大4B(mark区域变位8B,kclass区域被压缩),如果没有开启指针压缩,头部会大8B(mark和kclass都是8B),换句话说,

HotSpot的对齐方式为8字节对齐:(对象头+实例数据+padding)%8 等于0 且 0<=padding<8。

个人测试:

  Mark Word kclass 实例数据 引用 Padding
32位 4Byte 4Byte   未测试过  
64位未开启指针压缩 8Byte 8Byte   8Byte  
64位开启指针压缩 8Byte 4Byte   4Byte  

CASE


public class Peason {

    private int age;

}

/**
 * Unit test for simple App.
 */
public class AppTest 
{
    /**
     * Rigorous Test :-)
     */
    @Test
    public void shouldAnswerWithTrue()
    {
        Peason a = new Peason();
        System.out.println(ObjectSizeUtil.sizeOf(a));

        Peason[] array = new Peason[1];
        System.out.println(ObjectSizeUtil.sizeOf(array));

        array = new Peason[2];
        System.out.println(ObjectSizeUtil.sizeOf(array));
    }
}

结果:

64位未开启指针压缩

24

32

40

原因:

24:Mark Word 8字节 + kclass 4字节 + 4字节的padding填充 + 4字节实例数据+4字节padding填充

32:Mark Word 8字节 + kclass4字节 + 4字节padding填充 + 4字节数组长度 + 4字节padding填充+8字节引用

40:Mark Word 8字节 + kclass4字节 + 4字节padding填充 + 4字节数组长度 + 4字节padding填充+8字节引用 + 8字节引用

64位开启指针压缩

16:Mark Word 8字节 + kclass 4字节 + 4字节实例数据

24:Mark Word 8字节 + kclass4字节 + 4字节数组长度 + 4字节引用 + 4字节padding填充

24:Mark Word 8字节 + kclass4字节 + 4字节数组长度 + 4字节引用 + 4字节引用


猜你喜欢

转载自blog.csdn.net/u012210451/article/details/80944120