对象内存布局

对象的内存布局

在Hotspot虚拟机里,对象在内存中的内存布局可以划分为三个部分:对象头、实例数据以及对齐填充。

  • 对象头:包括了对象的类型、GC信息、锁状态和哈希码等基本信息。
  • 实例数据:主要是存放对象的类自身属性信息以及父类的属性信息,如果一个类没有字段属性,就不需要实例数据域
  • 对齐填充数据:虚拟机规范要求每个对象所占内存字节数必须是 8 的倍数。

对象头:对象头主要包含三个部分

  • Mark Word:主要包含 锁的标记、对象GC年龄、哈希码、偏向锁等信息。
  • Class Pointer:指向对象所属的 Class 在元数据区的内存指针,通常在32位系统占4字节,在64位系统中占8字节,64位 JVM 在 1.6 版本后默认开启了压缩指针 占用4个字节
  • Length:如果对象是数组,还需要一个保存数组长度的空间,占 4 个字节

    Mark Word 结构如下图所示

实例数据:实例数据里面主要是对象的字段数据信息。

对齐填充:JVM 堆中所有对象分配的内存字节总数必须是 8 的倍数,如果对象头和实例数据占用的总大小不满足要求,则需要通过对齐数据来填满

  •  计算机处理器读取内存数据时不是逐个字节去访问,而是以内存访问粒度(2、4、8、16 字节的块) 为单位访问内存。这样做的目的是减少内存访问次数,加快执行速度
  • JVM 内存对齐的原因:基于内存访问方式,对于未对齐地址的内存数据,处理器一次访问非常可能在这块内存中取到不需要的数据,必须额外做一些移除不需要的数据的工作,再将其放置在寄存器中,这会严重影响内存访问效率,JVM 要求内存对齐是为了计算机高效寻址,快速读取对象数据

代码示列:

 static class User{
        private Long id;
        private String name;
    }

    public static void main(String[] args){
        User user = new User();
        System.out.println(ClassLayout.parseInstance(user).toPrintable());
    }

 对象中各个部分内存占用如下:

  • 对象头中 Mark Word 占用 8 字节,类对象指针占用 4 字节,总共占用 12 字节
  • User对象的属性 id 和 name 各占 4 字节,总共占用 8 字节
  • 对齐填充以上两个部分总共占用 20 字节, 不满足 8 的倍数,所以需要填充 4 字节。

数组对象示例:

static class User{
        private Long id;
        private String name;
    }

    public static void main(String[] args){
        User user1 = new User();
        User user2 = new User();
        User[] users = new User[]{user1, user2};
        System.out.println(ClassLayout.parseInstance(users).toPrintable());
    }

 对象中各个部分内存占用如下:

  • 对象头中 Mark Word 占用 8 字节,类对象指针占用 4 字节,总共占用 12 字节
  • 数组长度 & 对齐填充数据 数组长度为 2,占用 4 字节
  • 实例数据  数组有两个User 对象,引用指针 共占用 8 字节,至此数组对象总大小 24 字节,满足 8 的倍数,因此不需要填充。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值