栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Java

熟悉HotSpot中的对象

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

熟悉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虚拟机》
转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1039309.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号