美文网首页
2.3Hotspot虚拟机对象探秘

2.3Hotspot虚拟机对象探秘

作者: 怡红快绿 | 来源:发表于2018-11-29 19:02 被阅读0次

一、对象的创建

在语言层面上,创建对象通常仅仅是一个new关键字而已,但是虚拟机中却要执行多个步骤:
1、检查这个指令的参数能否在常量池中定位到一个类的引用符合,并检查这个类是否被加载、解析和初始化过,如果没有必须先执行此类步骤。类加载检查通过后,就可以为对象分配内存。即把一块内存从Java堆中划分出来。

  • 指针碰撞
    Java堆中内存是绝对规整的,把已使用和空闲内存分为两边,中间用一个指针作为分界点的指示器,分配内存就是将指针向空闲内存方向移动与对象大小相等的距离。
  • 空闲列表
    Java堆中内存不是绝对规整的,已使用内存与空闲内存是相互交错的,虚拟机维护着一个列表,记录着内存使用情况。需要给对象分配内存的时候,就直接在列表内查找合适大小的内存空间划分给示例对象,并更新列表记录。

两种分配方式由Java堆是否规整来决定,而Java堆是否规整又取决于垃圾收集器是否带有压缩整理功能。

还有另外一个需要考虑的问题是对象的创建过程是非常频繁的,因此简单地修改指针位置在并发情况下不是线程安全的,可能正在准备给对象A分配内存,指针还未完成修改,此时对象B又使用原来的指针请求分配内存。解决这个问题有两种方案:

  • 对内存分配动作进行同步处理,同时要保证更新操作的原子性;
  • 另一种是把每个线程的内存分配动作划分在不同空间进行,即每个线程在Java堆中预先分配一小块内存,本地线程分配缓冲(TLAB),线程都在各自的TLAB上分配内存,当TLAB用完并分配新的TLAB时,才需要同步锁定。

2、内存分配完成后,虚拟机需要将分配到的内存初始化为零值,保证对象的实例字段可以不赋初始值就直接使用。

3、接下来,虚拟机需要对对象进行必要的设置。例如这个对象是哪个类的实例、如何找到类的元数据信息、哈希码、GC分代年龄等信息。这些信息存放在对象头中。

从虚拟机的角度来说,一个新的对象已经产生,但从Java程序的角度来看,一切才刚刚开始,类还没有执行一系列的初始化步骤,所有字段都还为零。只有当<init>方法执行完毕,一个真正可用的对象才算是生产出来了。

二、对象的内存布局

Hotspot虚拟机中,对象在内存中的布局分为三个区域:对象头、实例数据和对齐填充。

三、对象的访问定位

Java程序需要通过栈上的reference数据来操作堆上的具体数据。

  • 句柄访问
    句柄访问的好处是reference中储存的是稳定的句柄地址,对象被移动时只会改变实例数据指针,不会修改reference。
句柄访问
  • 指针访问
    指针访问的优点是速度快,它节省了一次指针定位的时间开销。
指针访问

相关文章

网友评论

      本文标题:2.3Hotspot虚拟机对象探秘

      本文链接:https://www.haomeiwen.com/subject/rkpnqqtx.html