JAVA虚拟机(二) HotSpot虚拟机对象模型

1. HotSpot虚拟机对象探秘
1.1 对象的创建
在语言层面来讲,创建对象通常只需要一个new关键字即可。
在虚拟机中,当遇到一个new指令时,首先会判断这个对象对应的类是否已经被加载,解析和初始化过,如果没有,必须先执行类的加载过程。
类加载检查通过后,会为新生对象分配内存,对象所需要的内存的大小在类加载完后便可以完全确定。
内存分配通常采用“指针碰撞”和“空闲列表”两种方式。选用哪种方式取决于内存是不是规整的。如果是规整的,用一个标记的指针就能确定新对象所方的内存位置,如果是不规整的,必须维护一个列表来确定哪块内存可以使用。
内存分配还会有线程安全问题,虚拟机采用CAS加上失败重试的方式保证操作的原子性。另一种方式是使用本地线程分配缓冲,即每个线程在Java堆中预先分配一小块内存。
内存分配完成后,虚拟机需要将分配的内存空间都初始化为零(不包括对象头)。然后设置一些必要的信息,比如,对象是哪个类的实例,如何才能找到类的元数据信息,对象的哈希码,GC分代年龄信息等,这些信息存放在对象头中。
执行初始化方法init后,这个对象就算完全产生出来了。
1.2 对象的内存布局
在HotSpot虚拟机中,对象在内存中的存储布局分为三个区域,对象头(Header),实例数据和填充信息。
对象头包括两部分信息,第一部分用于存储对象自身的运行时的数据,如哈希码,GC分代年龄,锁状态标志,这部分数据长度在32位和64位的虚拟机中分别为32bit和64bit,官方称为Mark Word。对象头的另一部分是类型指针,虚拟机通过这个指针来请确定这个对象是哪个类的实例。
实例数据部分是对象真正存储的有效信息,也是程序代码中所定义的各种类型的字段内容。无论是父类继承的还是子类中定义的,都需要记录下来。
第三部分对其填充并不是必然存在的,也没有特别的含义,他仅仅起着占位符的作用。原因是HotSpot VM的自动内存管理系统要求对象的起始地址必须是8字节的整数倍。
1.3 访问对象定位
Java程序需要通过栈上的reference数据来操作堆上的具体对象。对象的访问方式是取决于虚拟机实现而定的。目前主流的访问方式是句柄和直接指针两种。
如果使用句柄方式访问的话,那么Java堆中将会划出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,句柄中包含了对象的实例数据(当前对象的具体信息)与类型数据(对象的类的信息)各自的具体地址。
在这里插入图片描述
如果使用直接指针访问,那么Java堆对象的布局中就必须考虑如何放置访问类型数据(直白点就是这个对象属于哪个类)相关的信息,而reference中存储的直接就是对象地址。
在这里插入图片描述
目前HotSpot虚拟机是使用直接指针方式来进行访问的。

猜你喜欢

转载自blog.csdn.net/bianhao92115/article/details/82970270