深入理解java虚拟机——虚拟机对象探索

声明:此系列博客为学习《深入理解java虚拟机 JVM高级特性与最佳实战》笔记

           更加详细的情况请参考书本内容

这里使用HotSpot虚拟机作为具体的探索对象

1.对象的创建

      相对于java开发者而言,创建对象通常就是一个new关键字而已,那么在虚拟机中,创建一个对象我们又经历了些什么

      创建对象在虚拟机中经历的过程:

       – 检查指令的参数是否能在常量池中定位到一个类的符号引用

       – 检查这个符号引用代表的类是否已经被加载,解析和初始化,如果没有,就必须先执行类的加载过程

       – 虚拟机为新的对象分配内存(对象所需要的内存的大小在类加载完成时就可以确定)

       – 虚拟机将分配到的内存空间都初始化为0值(不包括对象头)(部分虚拟机可提前这部分工作,例如TLAB)

       – 对对象进行必要的设置(哪个类的实例,类的元数据如何查找,对象的哈戏码,对象的GC分代年龄等信息),这些信息都存放在对象的对象头中

       – 初始化对象是数据,在虚拟机的角度上看,对象已经产生,但是从java的角度上看,初始化过程还没有开始,所有的字段都还是0,一般来说,在执行过new指令之后,会接着执行<init>方法,将对象按照程序员的意愿进行初始化,这样,对象的创建才算完全结束

1.1 对象内存分配选择

       java中对对象分配内存有两种形式:指针碰撞空闲列表

       主要的区分方式取决于java堆中内存是否是绝对规整的

指针碰撞:

       假定java中堆内存是绝对规整的,所有已经使用的内存放在一边,未使用的内存放置在另一边,中间是一个指针作为分界点的指示器,那么分配内存本质上就是将指针向空闲空间方向一个与对象所需内存大小一致的距离

空闲列表:

       如果java堆内存不是规整的,已经使用的和未使用的相互交错,那么指针操作就失去意义了,这时候虚拟机就需要维护一个列表,记录哪些是已经使用的,哪些是可以使用的,在分配的时候早一个足够大的空间分配给对象,并修改列表上的记录为已使用

       注意:Java堆内存是否规整取决于垃圾回收机制是否有压缩整理功能

高并发下的内存分配

       高并发下,虚拟机创建对象的行为更加平凡,但靠一个指针很难确保线程安全,可能出现一个对象A正在分配内存,指针位置还没有更新,B对象又使用了原先的指针位置

       解决方式:

       1.对分配内存空间动作进行同步处理——事实上虚拟机采用的是CAS配上失败重试的方式确保更新操作的原子性

       2.将内存分配工作按照线程划分在不同的空间中进行,即每个线程在Java堆中预先分配一小块内存,称之为本地线程分配缓冲(TLAB)

1.2 对象的内存布局

       在HotSpot虚拟机中,对象在内存中存储的布局可以分为3个区域:对象头(Header)、实例数据(Instance Data)和对齐填充

对象头:

        对象头中包含有两部分的内容,分别是:

        《深入理解java虚拟机——虚拟机对象探索》

实例数据:

       存储的是对象中真实的数据,主要有以下的几个方面:

       – 对象中存储的字段信息(包括继承自父类的字段信息),这部分的存储顺序会根据虚拟机分配策略的影响

对齐填充:

       这部分的存在并不是必要的,主要是起到占位符的作用

       因为HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,即对象的内存为8字节的整数倍

1.3 对象的定位

       java中需要通过虚拟机栈中的reference数据来操作堆中对应的对象,因为java虚拟机规范中规定的栈中存储的只是指向对象的引用,并没说明具体的指向方式,所以对象的指向方式具体取决于虚拟机的实现,一般来讲,有句柄和直接指针两种方式:

句柄访问:

       Java堆中会开辟出来一块内存用来做句柄池使用,reference数据中存放的是对象的句柄地址,句柄中则包含了对象的实例数据与类型数据各自的地址:

     《深入理解java虚拟机——虚拟机对象探索》

直接访问

       使用直接访问时,就必须考虑在java堆对象布局中放置对象类型数据的指针信息,此时reference中存放的就直接是对象的地址

     《深入理解java虚拟机——虚拟机对象探索》
       两种方式的优缺点:

       句柄方式:对象实例数据地址放生变化的时候,只需要更改句柄池中对应的实例数据地址即可,而不需要对reference中的数据进行变更

       直接访问的方式则更加直接高效,更能节省资源

    原文作者:java虚拟机
    原文地址: https://blog.csdn.net/weixin_40326107/article/details/81737621
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞