HotSpot虚拟机对象

HotSpot虚拟机对象

对象内存模型

  • 结构:

    • 对象头(Header)
    • 实例数据(Instance Data)
    • 对齐填充(Padding)
  • 对象头:

    • 对象指针(类型指针/数组长度/...)
    • 哈希码
    • GC分代年龄
    • 锁状态标志
    • 线程持有的锁
    • 偏向线程ID
    • 偏向时间戳
  • 实例数据:

    • 父类成员变量
    • 本类成员变量
  • 对齐填充: 确保对象的内存大小是8字节的整数倍(Hotspot VM自动内存管理机制)

对象创建过程

  • 类加载检查
     虚拟机在解析.class文件时,若遇到一条 new 指令,首先它会去检查常量池中是否有这个类的符号引用,并且检查这个符号引用所代表的类是否已被加载、解析和初始化过。如果没有,那么必须先执行相应的类加载过程。

  • 为新生对象分配内存
     从堆中划分一块对应大小的内存空间给新的对象, 分配堆中内存有两种方式:

    • 指针碰撞
      如果 Java 堆中内存绝对规整(说明采用的是“复制算法”或“标记整理法”),空闲内存和已使用内存中间放着一个指针作为分界点指示器,那么分配内存时只需要把指针向空闲内存挪动一段与对象大小一样的距离,这种分配方式称为“指针碰撞”。

    • 空闲列表
      如果 Java 堆中内存并不规整,已使用的内存和空闲内存交错(说明采用的是标记-清除法,有碎片),此时没法简单进行指针碰撞, VM 必须维护一个列表,记录其中哪些内存块空闲可用。分配之时从空闲列表中找到一块足够大的内存空间划分给对象实例。这种方式称为“空闲列表”。

  • 对象初始化
     分配完内存后,为对象中的成员变量赋上初始值,设置对象头信息,调用对象的构造函数方法进行初始化。

对象访问过程

  • 对象的实际存储是在堆中,堆栈中会分配一块区域存储对象的引用

  • 根据对象类型,访问方式分为:

    • 句柄访问方式(两次寻址)
       存储对象的句柄地址(reference),访问时要先找到对象的句柄,在句柄中根据对象地址找到对象。句柄池存在于堆中。

    • 直接指针访问方式(一次寻址)
       直接存放指向堆中对象实例数据的指针,对象的类型数据存放在方法区中。

原文地址:https://www.cnblogs.com/CodeSPA/p/13561747.html