深入理解java虚拟机

深入理解java虚拟机额---HotSpot虚拟机对象探秘


本博客所有内容为阅读《深入理解java虚拟机》小结,如有侵权,请联系删除。
书接上文,接下来探讨HotSpot虚拟机在Java堆中对象分配、布局和访问全过程。
下文讨论的对象仅限于普通java对象,不包括数据和class对象等。

对象的创建

在类加载检查通过之后,接下来虚拟机将为新生对象分配内存。对象所需内存大小在类加载完成后便可确定。
分配内存的两种方式:指针碰撞(Bump The Pointer)适用于堆内存绝对规整、空闲列表(Free List)适用于堆内存不规整,所谓的空闲列表是指虚拟机维护一张列表,记录上哪些内存块是可用的,在分配内存的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的记录。选择哪种分配方式由java堆是否规整决定,而java堆是否规整又由所采用的垃圾收集器是否带有空间压缩整理(Compact)的能力决定,因此,当使用Serial、ParNew等带压缩整理过程的收集器时,系统采用的分配算法是指针碰撞,既简单又高效;而当使用CMS这种基于清除(Sweep)算法的收集器时,理论上就只能采用较为复杂的空闲列表来分配内存。
在高并发情况下,可能会出现正在给对象A分配内存,在指针还没来得及修改时,对象B又同时使用原来的指针分配内存的情况。解决这个问题有两个方案:CAS配上失败重试(虚拟机默认是这个方法)、哪个线程分配就在哪个线程的TLAB中分配,只有TLAB用完了,分配新的缓存区时才需要同步锁定(通过-XX:+/-USeTLAB参数设定)。
内存分配完成之后,虚拟机必须将分配的内存空间(不包括对象头)都初始化为零值。并设置对象头。
上面工作完成之后,对对象进行初始化。

对象的内存布局

HotSpot虚拟机中,对象在堆内存中的存储布局可以划分为三个部分:对象头(Header)、实例数据(InstanceData)和对齐填充(Padding)。
对象头包括两类信息:自身运行时数据(hashcode、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等),这部分数据的长度在32位和64位虚拟机中分别为32个比特和64个比特。官方称为Mark Word。对象头的另外一部分是类型指针,即对象指向他的类型元数据的指针。如果对象是一个数组,在对象头中还必须有一块用于记录数组长度的数据。
实例数据部分是对象真正存储的有效信息。
对齐填充并不一定存在,由于hotspot虚拟机的自动内存管理系统要求对象的其实地址必须是8字节的整数倍,换句话说任何对象的大小都必须是8字节的整数倍。

对象访问定位

java程序会通过栈上的reference数据来操作堆上的具体对象。主流的访问方式主要有使用句柄和直接指针两种。
句柄存储在java堆中,包含对象实例数据与类型数据各自具体的地址信息,reference中存储的是对象句柄的地址。
如果使用直接指针访问,java堆中的内存分布必须考虑如何放置访问类型数据的相关信息,reference中存储的直接就是对象地址。(Hotspot主要使用这种)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值