• 熟悉HotSpot中的对象


    对象的内存布局

    在HotSpot虚拟机中,对象的内存布局分为以下3个区域:

    • 对象头
    • 实例数据
    • 对齐填充
      在这里插入图片描述

    对象头

    对象头包含Mark Word和类型指针2个部分。如果是数组对象,则有一部分存储数组的长度。
    Mark Word中存储:

    • 哈希吗(HashCode)
    • GC分代年龄
    • 锁状态标志
    • 线程持有的锁
    • 偏向线程ID
    • 偏向时间戳

    类型指针

    类型指针Klass存储该对象的类对象的内存地址,可以通过该指针知道对象是属于哪个类。

    实例数据

    实例数据部分就是成员变量的值,其中包括父类成员变量和本类成员变量。

    对齐填充

    保证对象内存大小是8字节的倍数,不足的部分按填充对齐。

    对象的创建过程

    在这里插入图片描述

    1. 类加载检查
      先检查对象的类是否加载,没有加载则先加载类。(类加载完成后就能计算出对象的大小,请参考Java如何计算对象大小
    2. 内存分配
      给对象分配内存,如果使用TLAB,则优先在TLAB空间分配,再在Eden区分配。如果内存规整则使用指针碰撞方式分配内存,不规整则使用空闲列表方式分配内存。
    • 指针碰撞
      内存规整(说明垃圾回收采用的是标记整理算法),已使用内存和空闲内存分界线上放着一个指针左为分界指示器。只需要将指针移动往空闲内存一端移动对象大小的距离。
    • 空闲列表
      内存不规整(说明垃圾回收采用的是标记清除算法,有碎片),那么VM必须维护一个列表,记录哪些内存是空闲可用的,分配时从空闲列表中找到一块足够大的内存给对象示例使用。
    1. 初始化
    • 设置零值
      内存分配完成后,虚拟机会将分配到内存的空间都初始化为零值。(不包含对象头)
      这也保证了Java代码不赋值初始化就直接使用,程序能访问到这些字段的数据类型对应的零值。
    • 设置对象头信息
      – 设置klass指针为对应类对象的地址
      – 对象的hashCode
      – 对象的分代年龄 等
    • 执行构造方法
      执行对象所属类定义的init构造方法,完成初始化。

    至此,一个可用的对象才算是完全创建出来。

    对象的访问方式

    对象的存储空间是在堆中分配的,但是这个对象的引用(存的是地址)却是在栈中分配的。
    Java程序通过栈上的reference引用来操作堆上的具体对象。

    目前对象的访问方式有句柄访问和直接指针访问方式。

    句柄访问方式在这里插入图片描述

    对象引用内存储的是指向句柄地址,句柄对象中包含对象实例数据指针和类型数据指针。

    直接指针访问方式在这里插入图片描述

    对象引用中存储的是对象实例数据指针,再通过对象头里的klass指针找到对象类型数据。

    总结:
    使用句柄方式访问,优点是对象变化时栈中的reference的值不用改变,存储的是稳定的句柄地址;
    而使用直接指针方式访问最大好处就是速度更快,它节省了一次指针定位的时间开销。
    HotSpot虚拟机采用直接指针的对象访问方式。

    参考资料

    • 周志明 * 《深入理解Java虚拟机》
  • 相关阅读:
    安卓ROM定制 修改必备常识-----初步了解system系统分区文件夹的基本含义 【二】
    java中Date类之GMT、UTC
    指针应用(二)
    如何基于YAML设计接口自动化测试框架?看完秒会
    Go语言网络编程(socket编程)UDP
    Mysql锁
    FOXBORO FBM233 控制主板模块
    3D激光SLAM:Livox激光雷达硬件时间同步
    新知实验室-基于腾讯云音视频TRTC的微信小程序实践
    Python数据挖掘:入门、进阶与实用案例分析——自动售货机销售数据分析与应用
  • 原文地址:https://blog.csdn.net/mg0324/article/details/126253018