hotspot虚拟机在java堆中对象分配布局和访问的全过程

来源:互联网 发布:json格式 java 编辑:程序博客网 时间:2024/04/29 06:19

new 指令

  1. 先检查常量池中 有没有该类的符号引用,并检查该类是否已被加载 解析和初始化过,如果没有则加载该类
  2. 为新生对象分配内存(一个对象所需内存在类加载完成之后便可以确定了)分配内存及把一块确定大小的内存区域从java堆中划分出来

    分配方式:

    指针碰撞空闲列表

    线程不安全,为保证线程安全:

    失败重试划分缓冲区:即为每个县城划分一个本地线程分配缓冲(TLAB),哪个线程要分配内存就在哪个线程的缓冲区上分配,当TLAB用完时,会为该线程重新分配TLAB
  3. 初始化零值

    将分配到的内存都初始化为零值,这样对象的实例字段可以不赋初始值就可以使用,程序可以访问到对应数据类型的零值
  4. 设置对象头

    该对象是哪个类的实例,如何才能找到类的元信息,对象的哈希码(hashcode),对象的GC年龄分代信息,是否使用偏向锁等     
  5. init

         执行完上述过程程序才被创建,之后会继续执init方法,把对象按照程序员的意愿进行初始化,一个真正可用的对象才被生产出来

对象在内存中的存储

    对象在内存中主要有三部分:对象头、 实例数据、 对齐填充
  1. 对象头

    主要包括运行时数据、 类型指针运行时数据:hashcode GC分代年龄 锁状态标识 线程持有的锁 偏向线程ID 偏向时间戳 这些称为MarkWord类型指针:对象指向类元数据的指针,类型指针数据长度:如果 是java数组 还要有用于记录数组长度的数据(普通对象可以通过类元数据信息获取java对象的大小 而对于数组并不能)
  2. 列表内容

    子类或者父类中的实例数据都会被记录下来
  3. 对齐填充

    保证对象的起始地址是8字节的整数被,而用于填充的部分

对象的定位访问

句柄和直接指针
  1. 句柄

    reference指向java堆中的句柄池,句柄包含了对象实例数据与理性数据的地址
    这里写图片描述

  2. 直接指针

    接指针存储的就是对象实例数据地址,但实例数据中应该要包含对象类型数据
    这里写图片描述

0 0