Java对象布局

一、Java对象的布局

在 HotSpot虚拟机中,对象在内存中的存储的布局可以分为三块区域:对象头(Header)实例数据(Instance Data)对齐填充(Padding)

如下图:

 1.1 对象头

Mark Word:包含一系列的标记位,比如轻量级锁的标记位,偏向锁标记位等等。在32位系统占4字节,在64位系统中占8字节

Class Pointer(类型指针):用来指向对象对应的Class对象(其对应的元数据对象)的内存地址。在32位系统占4字节,在64位系统中占8字节

Length:如果是数组对象,还有一个保存数组长度的空间,占4个字节

1.1.1 Mark Word 

Mark Word是一个8字节的头,记录着锁信息,GC信息,还有HashCode。锁定了某个对象后,实际上是修改了Mark Word的内容。

1.2 实例数据

对象实例数据 : 对象的所有成员变量,其中包含父类的成员变量和本类的成员变量,也就是说,除去静态变量和常量值放在方法区,非静态变量的值是随着对象存储在堆中的

byte、boolean是1个字节,short、char是2个字节,int、float是4个字节,long、double是8个字节,reference是4个字节(64位系统中是8个字节)。

1.3 对齐填充

由于 HotSpot VM 的自动内存管理系统要求对象起始地址必须是 8 字节的整数倍,也就是说对象的大小必须是 8 字节的整数倍。

对象头部分是 8 字节的倍数,所以当对象实例数据部分没有对齐时,就需要通过对齐填充来补全。

Java一个对象占多少字节,根据上面所述,我们知道 占用16字节,下面具体详述:

64位系统(未开启指针压缩):Mark Word占用8个字节 + Class Pointer占用8个字节 = 16个字节 (16已经是8的整数倍,所以不需要对齐填充)   -》对象头的大小:16个字节

64位系统(开启指针压缩):Mark Word 占用8个字节 + Class Pointer 占用4个字节 + 对齐填充 4个字节 = 16个字节 (空对象,所以实例数据大小为0) -》对象头的大小:12个字节 

二、JOL工具

JOL = Java Object Layout,即Java对象布局,可以帮助我们查看对象布局

2.1 引入依赖

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

2.2 测试Demo

2.2.1 默认开启指针压缩

public class JOLExample1 {

    static A a =new A();

    public static void main(String[] args) {
        System.out.println(VM.current().details());

        System.out.println("----------------------------------------------------------------------------");

        System.out.println(ClassLayout.parseClass(A.class).toPrintable());

        System.out.println("----------------------------------------------------------------------------");

        System.out.println(ClassLayout.parseInstance(a).toPrintable());

        System.out.println("----------------------------------------------------------------------------");

        synchronized (a) {
            System.out.println(ClassLayout.parseInstance(a).toPrintable());
        }

    }
}

class A {

}

综上我们可以看出实际的结果也是16字节,指针压缩Class Pointer的大小压缩成了4个字节:

64位系统(开启指针压缩):Mark Word 占用8个字节 + Class Pointer 占用4个字节 + 对齐填充 4个字节 = 16个字节 (空对象,所以实例数据大小为0)  

对象头的大小:12个字节

2.2.2 关闭指针压缩

 -XX:-UseCompressedOops 

 

64位系统(未开启指针压缩):Mark Word占用8个字节 + Class Pointer占用8个字节 = 16个字节 (16已经是8的整数倍,所以不需要对齐填充)

指针压缩:开启指针压缩使用算法开销带来内存节约

-XX:+UseCompressedOops 

注意:32位HotSpot VM是不支持UseCompressedOops参数的,只有64位HotSpot VM才支持。

注意:下面的所有测试,都是开启了指针压缩的

三、实例数据

3.1 添加一个int类型

 3.2 对齐填充的位置

 4字节 => 12字节(对象头)+5个字节(实例数据:byte 1个字节+String 引用 4个字节)+7个字节(对齐填充)

在 HotSpot VM 中,对象排布时,间隙是在 4 字节基础上的(在 32 位和 64 位压缩模式下),

上述例子中,byte为一个字节,空隙只剩下 3 字节,接下来的 String 对象引用需要 4 字节来存放,

因此 byte 和对象引用之间就会有 3 字节对齐,对象引用排布后,最后会有 4 字节对齐,因此结果上依然是对齐需要7个字节

 3.3 字段重排序

字段重新排序了,我们发现 short排在了最前面,byte在后面,然后对齐填充(这里上面我们已经解释了原因),String在最后

short\char 会排在byte\boolean的前面

3.4 静态变量

对象实例数据instance data : 对象的所有成员变量其中包含父类的成员变量和本类的成员变量,

也就是说,除去静态变量和常量值放在方法区,非静态变量的值是随着对象存储在堆中的。

 3.5 父类的成语变量

 视频教程参考博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值