轻松get JVM——HotSpot虚拟机对象

不同的虚拟机中对象的具体分布是不同的,目前Hotspot虚拟机使用的较为广泛,以该虚拟机为例,撰写一下Java堆中对象分配、布局和访问的全过程

Java对象的创建

首先需要提的是,Java的对象创建只能通过new指令

Java作为一种“安全”的语言,检查是家常便饭,new操作就存在了检查

new指令的过程:

类加载检查

  1. 检查该指令的参数能否在常量池中定位到
  2. 检查该类是否已经被加载
  3. 若为加载,则执行相应的类加载过程

虚拟机为新生对象分配内存

在这里开始描述前,有必要提前说明:对象在内存中占用的空间的确定的

逻辑很简单,从堆中分配内存。

但是因为Java垃圾回收、高并发的原因,存在以下几个问题:

划分内存的方法

  1. 堆中内存是规整的,“指针碰撞

    使用过的内存放一边,未使用过的放在另一侧,中间使用一个指针作为分界点指示。

    这种情况只需要移动指针即可,称为“指针碰撞

    内存规则

  2. 堆中内存不规整,“空闲列表

    使用过的内存与空闲内存相互交错,虚拟机需要维护一个记录表,记录可用的内存块,分配时寻找合适的内存块进行分配,称为“空闲列表

分配空间时,由于多线程操作导致的问题

假设有三个线程,同时向虚拟机申请内存,若一起处理,势必造成数据错乱

虚拟机有两个方案来应对这个情况:

  1. 对分配空间进行同步处理。

    虚拟机采用了CAS配合失败重试的方式保证更新操作原子性

    CAS:

    Compare And Swap ,一种无锁的方式处理并发,给数据标记,每次操作进行加1,结束后核实该标记是否被改动

  2. 将内存划分为小块进行分配。

    每个线程预先在Java堆中分配一小块内存,称为本地线程分配缓冲

对象初始化

所有空间都初始化为零值(不包括对象头)

零值:引用统一为null,布尔为false,其他均为0

对象头进行必要的设置

设置该对象为哪个对象的实例、寻找类的元数据的方式、对象哈希码、对象的GC分代年龄信息等。

执行初始化程序

方法执行,根据用户编码进行初始化。

总结如下

Java对象初始化流程

Java对象的内存布局

在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块

对象头(Header),实例数据(Instance Data),对齐填充(Padding)

对象头

对象头包括两部分:自身运行时数据与类型指针

  1. 自身运行时数据

    哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等

    存储在32bit或64bit

    称为“Mark Word

    非固定的数据结构,以便于高效存储尽可能多的信息,根据对象状态复用自己的空间。

  2. 类型指针

    对象指向它的类元数据的指针,通过该指针,可以得知对象的类型

  3. 若为数组,则对象头中还有一块用于记录数组长度的数据

实例数据

程序代码中所定义的各种类型的字段内容。父类继承与子类定义都被记录。

存储顺序受虚拟机分配策略参数和字段在Java源码中定义顺序的影响。

对齐填充

无特别意义,保证对象大小为8字节的整数倍

img

对象的访问定位

Java通过reference类型代表对象的引用。

Java虚拟机未规定该引用怎样定位对象的具体位置

Reference有两种主流方式寻找对象具体位置:句柄和直接指针

句柄访问

Java堆中划出一块内存作为句柄池,reference中存储对象的句柄地址,句柄中包含对象的实例数据与类型数据各自的具体地址信息。

句柄访问

句柄

程序设计中,句柄handle)是Windows操作系统用来标识被应用程序所创建或使用的对象的整数。其本质相当于带有引用计数的智能指针。当一个应用程序要引用其他系统(如数据库操作系统)所管理的内存块或对象时,可以使用句柄。

句柄与普通指针的区别在于,指针包含的是引用对象内存地址,而句柄则是由系统所管理的引用标识,该标识可以被系统重新定位到一个内存地址上。这种间接访问对象的模式增强了系统对引用对象的控制。(参见封装)。通俗的说就是我们调用句柄就是调用句柄所提供的服务,即句柄已经把它能做的操作都设定好了,我们只能在句柄所提供的操作范围内进行操作,但是普通指针的操作却多种多样,不受限制。

直接指针访问

Java堆对象的布局中放置类型数据的相关地址信息,reference中存储的就是对象地址

直接指针访问

两种方式的比较

  1. 句柄访问:reference中存储的是句柄地址,对象被移动(垃圾回收为了整理空间,会普遍发生移动)时,改变句柄中实例数据指针就行。
  2. 直接指针:直接指针速度更快,节省了一次指针定位的开销,HotSpot采用了直接指针。

有用点个赞吧,欧尼该!

猜你喜欢

转载自blog.csdn.net/weixin_44494373/article/details/107303530