对象内存布局

大纲

前言


我的所有文章同步更新与Github–Java-Notes,想了解JVM(基本更完),HashMap源码分析,spring相关,,并发,剑指offer题解(Java版),可以点个star。可以看我的github主页,每天都在更新哟。

邀请您跟我一同完成 repo


在HotSpot中,对象在内存中存储的布局可以分为三个区域:

  • 对象头
  • 实例数据
  • 对齐填充

下面我们就挨个说下这三个东西到底是啥,有啥东西

一定要重点注意第一个对象头里的东西,因为讲并发时锁优化还有对象创建会用到这个

对象头

对象头里存两个部分的信息

  • 运行时数据(Mark Word)
  • 类型指针(Class Pointer)

运行时数据

这里主要存对象自身的运行时数据,比如

  • 哈希码
  • GC分代年龄
  • 锁状态标志
  • 线程持有的锁
  • 偏向线程ID
  • 偏向时间戳
  • 等……

用图看下就知道了

长度

  • 对象是数组类型
    • 3字宽(32位虚拟机中,一字宽=4字节=32bit;64位虚拟机乘2)
  • 非数组类型
    • 2字宽(不同虚拟机位数,同上)

注意这个里面的数据是会随着锁标志位变化而变化

类型指针

Class Point,用来指向对象对应到Class对象(其对应的元数据)内存地址。

32 位中 占4个字节,64位占8个字节。

Array Length(数组长度,数组对象才有)

32位的JVM上,长度为32位;64位JVM则为64位。

64位JVM如果开启+UseCompressedOops选项(开启指针压缩),该区域长度也将由64位压缩至32位。32位HotSpot VM是不支持UseCompressedOops参数的,只有64位HotSpot VM才支持。

实例数据

实例数据才是对象真正存储的有效信息,也是在程序代码中所定义的各种类型的字段内容。

无论是从父类继承下来的,还是在子类定义的,都需要记录下来。这部分的存储顺序受到虚拟机分配策略参数字段在Java源码中定义顺序的影响

HotSpot虚拟机默认的分配策略为longs/doubles、ints、short/chars、bytes/booleans、oops(普通对象指针,在垃圾回收文章的安全区会见到),可以看到,相同宽度的字段总会分配到一起

在满足上面的那个前提下,父类中定义的变量会出现在子类中定义的变量之前,如果CompactFields参数值为 true,默认为 true,那么子类中定义的变量也可能会插到父类变量的空隙中。

对齐填充

这部分不是必然存在,只是位数不够,拿来填充,为了整齐,仅仅起到占位符的作用

因为HotSpot VM 的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说,就是对象的大小必须是 8字节的整数倍

发布了21 篇原创文章 · 获赞 6 · 访问量 3961

猜你喜欢

转载自blog.csdn.net/qq_35583772/article/details/92728006
今日推荐