对象通过new,反射,clone等方式创建完毕后被存储到堆中,那么对象是以什么样的方式存储在堆中的?

对象的内存布局

对象在堆内存的内存布局主要有三部分,即对象头,实例数据,对其填充

对象头

对象头主要包含两部分的内容,一个叫运行时元数据(mark word),一个叫类型指针

  • 1.运行时元数据
    • 哈希值(hashcode):对象在堆空间中都有一个首地址值,栈空间的引用根据这个地址指向堆中的对象,这就是哈希值起的作用
    • GC分代年龄:对象首先是在Eden中创建的,在经过多次GC后,如果没有被进行回收,就会在survivor中来回移动,其对应的年龄计数器会发生变化,达到阈值后会进入养老区
    • 锁状态标志,在同步中判断该对象是否是锁
    • 线程持有的锁
    • 线程偏向ID
    • 偏向时间戳
  • 2.类型指针,指向元数据区的代表当前类的class对象,确定该对象所属的类型

说明:如果对象是数组,则还需要记录数组的长度

实例数据(Instance Data)

它是对象真正存储的有效信息,包括程序代码中定义的各种字段类型(包括从父类继承下来的和自己本身拥有的字段),注意这里有一些规则:相同宽度的字段总是被分配在一起,父类中定义的变量会出现在子类之前,因为父类的加载是优先于子类加载的

对齐填充

没有特殊含义,仅仅起到占位符的作用