HotSpot中对象的创建、内存布局、访问定位

HotSpot是最常用的虚拟机,我们来看一下HotSpot中对象创建、布局、访问的过程

一、对象的创建

  • 类加载:当java虚拟机遇到了字节码new指令时,会首先检查指令的参数能否在常量池中定位到类的符号引用,检查类是否已经被加载,如果没有则先加载类
  • 给对象分配内存:类加载完成后就可以确定对象所需内存大小,接下来从堆中给对象分配一块内存。当使用Serial、ParNew等带有压缩整理过程的收集器时,可以用指针碰撞算法分配内存,如果是CMS收集器的话,则要用空闲链表
  • 保证分配时线程安全:有两种是实现 1:CAS实现同步 2:本地线程分配缓冲(TLAB),用-XX:+/-UseTLAB设定
  • 初始化1:设置对象头 2:初始化内存为零 3:执行<init>()方法

二、对象的内存布局

HotSpot中,对象内存布局可以分为三个部分:对象头(Header)、实例数据(Instance Data)、对齐填充(Padding)

1.对象头

  1. Mark Word
    根据32还是64位虚拟机,Mark Word也分32、64位。

用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等

  1. 类型指针
    指向类型元数据,虚拟机通过这个指针查找对象是哪个类的实例(不是所有虚拟机都实现了这个)。
  2. 如果是数组的话还要有一块记录数组的长度

2.实例数据

这部好像没啥特别的 QAQ 实例数据就是保存类的字段

实例数据部分是对象真正存储的有效信息,即我们在程序代码里面所定义的各种类型的字段内容,无论是从父类继承下来的,还是在子类中定义的字段都必须记录起来。

3.对齐填充

HotSpot要求对象起始地址必须是8字节整数倍,如果实例数据不满足要求的话需要填充

三、对象访问定位

Java程序会通过栈上的reference数据来操作堆上的具体对象,对于reference具体如何定位访问堆上的对象,虚拟机规范没有明确要求,主流的实现方式有两种。HotSpot是第二种方式

  1. 句柄:堆中专门划出一块句柄池,reference存储句柄地址,句柄存储了实例、类型的地址。
  • 这样做的好处是在垃圾回收移动了对象时,只需改变句柄内容就好了,而不需要去改变reference的内容
  • 坏处就是访问对象时需要两次访问内存
  1. 直接访问:reference存储对象地址,对象头中存储类型地址
  • 好处就是访问对象只需一次访存(不使用Shenandoah收集器的话)
  • 坏处是垃圾回收移动了对象时,需要改变reference存储的内容,另外,在访问类型数据时也需要两次访存

使用句柄
直接访问

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值