JVM 对象的内存分配与结构

JVM 对象的内存分配与结构

对象内存怎么分配?

在类加载检测通过后, VM就会为新生对象分配内存。为对象分配内存的操作,就是将内存划分一块大小和对象相等的内存空间。但是内存空间并不是绝对规整的,所以分配内存的过程就会有多种方式。当空闲内存和非空闲内存完全分开的情况下,即一边是空闲,另一边是非空闲,你们就会通过中间的指针滑动的方式分配,被称为“指针碰撞”。但是如果空闲的内存,零散的发布,就不能使用指针来操作了,VM就必须通过维护一个列表,记录上哪些内存块时可用的,在列表中找到一块足够大的空间划分给对象实例,这种方式被称为“空闲列表”。具体使用哪种分配方式,有Java堆的规整程度,和GC是否带有空间压缩整理的能力决定。

当然在实际划分的时候,还需要考虑一个问题:在虚拟机中创建对象是非常频繁的行为,任何修改操作,在并发的情况下也不是线程安全的。如果要解决这个问题,有2个方案。一种是对分配内存空间的动作同步处理,另一种是把内存分配的动作按照线程划分在不同的空间,每个线程空间都独立,每个线程在堆中预先分配一块内存(Thread Local Allocation Buffer)TLAB 本地线程分配缓冲。如果使用TLAB,可以通过-XX: +/-UseTLAB 来设定。

空间分配完成,VM就会将分配的内存空间(不含对象头)都初始化为零值。这步保证了对象的实例字段不赋初始值就可以直接用,访问这些字段类型所对应的零值。

对象的内存结构?

在HotSpot的虚拟机,对象在堆中的布局分为3个部分:对象头(Header)实例数据(Instance Data)对齐数据(Padding)

对象头包括2类信息,
  第一类是存储对象自身的运行时数据,哈希码HashCode,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳等,这部分被称为MarkWord在32位和64位机器上分别占32个bit和64bit。
  另一类是类型指针,即对象指向它的类型元数据的指针,JVM通过这个指针来确定该对象是哪个类的实例。并不是所有的虚拟机实现都必须在对象数据上保留类型指针。如果对象是一个JAVA数组,那在对象头中还会有一块用于记录数组长度的数据。

实例数据部分,是对象真正存储的有效信息,即我们再程序代码里面定义的各种类型的字段内容。

第三部分是对齐填充,这不是必然存在的,没有特别含义,仅仅起着占位符的作用。

对象怎么找?

如何定位对象?

Java程序会通过栈上的reference数据来操作堆上的具体对象。实际上主流的访问方式有句柄和直接指针2种。

使用句柄:

Java堆中将可能一块内存作为句柄池,reference中存储的对象的句柄对象,而句柄就包含了对象实例数据与类型数据各自具体的地址信息
img

使用直接指针:

reference存储的是对象地址,如果只访问对象,就不用多一次间接访问的开销。HotSpot使用的就是这个方法
imgimg

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Eric.Cui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值