JVM——java虚拟机创建对象与寻址对象

时间:2022-12-29 10:14:48

JVM——java虚拟机创建对象与寻址对象

JAVA虚拟机创建对象的流程

 

JVM——java虚拟机创建对象与寻址对象

JAVA对象的结构

空间分配

空间分配的两种方式

指针碰撞

    当已分配空间被集中存放,已分配和未分配空间使用一个指针来标记时,分配新的空间只需要移动该空间即可,此方法为指针碰撞。适用于GC算法会做COMPACT的情况。

空闲列表

    当已分配的空间是分散存放时,虚拟机必须维护一个记录了哪些内存块是可用的列表,此为空闲列表,需要分配新空间时只需要从该列表中获取。

解决空间分配线程安全问题的两种方式

CAS方式失败重试

    顾名思义,遇上分配时的线程冲突时,会再次进行空间分配直至成功。实现简单直观但是效率较低

空间划分

    为每个线程分配单独的一块空间,该空间只用来给该线程做创建对象分配空间时使用,这单独的空间被称为本地线程分配缓冲(Thread Local Allocation Buffer,TLAB)。当该线程的TLAB分配光了后,才需要同步锁定,效率较高。是否使用TLAB可以通过虚拟机参数指定。

设置对象头(对象管理的必要信息)

  空间初始化成0后(初始化不包含对象头),需要针对对象设置一些必要信息,如:对象归属于哪个类、对象的hash码、对象的GC分代年龄等,这些信息都放在对象头中。根据虚拟机状态——如是否使用偏向锁,设置对象头。

对象头包含信息

    对象头包含两部分信息:

      • 运行时数据(hash码、GC分代年两、持有锁、锁标识状态、偏向线程ID),这部分数据被称为Mark Word。
      • 类型指针,用来说明该对象是哪个类的实例。

设置对象实例数据

  对象的实例数据主要是根据JAVA代码的编写生成的,包含包括父类在内的各种类型的字段,其字段安排的顺序受虚拟机实现及代码的编写影响。

虚拟机安排字段的方式

    1、相同宽度的字段放在一起

    2、父类的字段放在子类的前面

    3、窄小的变量也会被安排在父类的字段空隙中(C++的内存安排规则,HotSpot VM是由C++语言编写)

填充字段

  HotSpot VM要求对象的其实位置必须是8字节的整数倍,也就是说对象必须是8字节的整数倍,所以需要填充占位(这也是一句C++的规则来的)。

 

对象的定位

  JAVA程序访问对象需要通过栈上的reference数据操作堆上的具体对象。reference对象要么通过指向句柄再指向对象实例,要么直接指向对象实例。

以句柄的方式访问

    使用句柄方式访问对象实例,需要在堆中划分出一块儿句柄池,句柄与指针类似,记录了具体的实例所存放的地址。这种方式的好处是reference是稳定的,当对象实例地址改变时,只需改变句柄中的对象实例指针。

JVM——java虚拟机创建对象与寻址对象

 

以指针直接访问

    以指针方式访问对象实例,是通过reference直接指向对象实例,优点是速度快,因为比句柄访问方式少了一次寻址的过程。

JVM——java虚拟机创建对象与寻址对象

 

PS:对象实例数据指的是具体的对象,对象类型对象指的是该实例数据对象所属的Class类对象。