【JVM】虚拟机对象的创建、布局和访问
基于虚拟机内存的概况了解,进一步了解虚拟机内存中的数据的其他细节,如它们是如何创建、如何布局以及如何访问的
本文以虚拟机HotSpot和常用的内存区域Java堆深入对象分配、布局和访问的全过程
对象的创建
(1)检查这个指令的参数能否在常量池中定位到一个类的符号引用,并检查这个符号引用代表的类是否被加载,解析,初始化,如果没有,先加载
(2)为新生对象在java堆中分配内存,相当于把一块确定大小的内存从Java堆里划分出来 ;
分配方式:
java堆如果规整,分配内存的方法可使用“指针碰撞“;
一边是用过的内存,一边是空闲的内存,中间一个指针作为边界指示器;
分配内存只需向空闲那边移动指针
如果不规整,则使用”空闲列表“。用过的和空闲的内存相互交错;
需要维护一个列表,记录哪些内存可用;
分配内存时查表找到一个足够大的内存,并更新列表,
选择哪种分配方式是根据这个虚拟机所采用的垃圾收集器是否带有压缩整理功能决定的。
在使Serial、 ParNew等带Compact过程的收集器时,系统采用的分配算法是指针碰撞
使用CMS这种基于Mark-Sweep算法的收集器时,通常采用空闲列表。
线程安全问题
并发时,上面两种方式分配内存的操作都不是线程安全的,有两种解决方案:
(I)、同步处理
JVM采用CAS(Compare and Swap)机制加上失败重试的方式,保证更新操作的原子性;
CAS:有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做;
(II)、本地线程分配缓冲区
把分配内存的动作按照线程划分在不同的空间中进行:
在每个线程在Java堆预先分配一小块内存,称为本地线程分配缓冲区(Thread Local Allocation Buffer,TLAB);
哪个线程需要分配内存就从哪个线程的TLAB上分配;
只有TLAB用完需要分配新的TLAB时,才需要同步处理;
JVM通过"-XX:+/-UseTLAB"指定是否使用TLAB;
(3)内存分配完之后,虚拟机需要将分配到的内存空间都初始化为零值。如果用TLAB,则在TLAB分配时进行。这保证了程序中对象(及实例变量)不显式初始赋零值,程序也能访问到零值;
(4)虚拟机对对象进行必要的设置,例如这个对象是哪个类的实例、 如何才能找到类的元数据信息、 对象的哈希码、 对象的GC分代年龄等信息。这些信息存放在对象的对象头(Object Header)之中。
(5)执行init方法,即按照程序员的意愿进行初始化。
对象的内存布局
在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据(InstanceData)、和对齐填充(Padding)。
对象头
①第一部分用于存储对象自身运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等,这部分数据的长度在32位和64位的虚拟机中分别为32bit和64bit,官方称它为“Mark Word”。
② 对象头的另外一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是那个类的实例。并不是所有的虚拟机实现都必须在对象数据上保留类型指针,换句话说,查找对象的元数据信息并不一定经过对象本身,另外,如果对象是一个Java数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通Java对象的元数据信息确定Java对象的大小,但是从数组的元数据中却无法确定数组的大小。
存储内容 | 标志位 | 状态 |
---|---|---|
对象哈希码、对象分代年龄 | 01 | 未锁定 |
指向锁记录的指针 | 00 | 轻量级锁 |
指向重量级锁的指针 | 10 | 膨胀(重量级锁) |
空、不需要记录信息 | 11 | GC标记 |
偏向线程ID、偏向时间戳、对象分代年龄 | 01 | 可偏向 |
对象的访问定位
建立对象是为了使用对象,Java程序通过栈上的reference数据来操作堆上的具体对象。
-
直接指针访问要比句柄访问快一些,因为减少了一次指针定位的时间开销。
-
句柄来访问的最大好处就是reference中存储的是稳定的句柄地址
参考资料:
JVM系列二(虚拟机对象创建、布局、定位):https://blog.csdn.net/u013292160/article/details/74931254
Java对象与JVM(一) Java对象在Java虚拟机中的创建过程:https://blog.csdn.net/tjiyu/article/details/53923392
《Java虚拟机原理图解》3、JVM运行时数据区:https://blog.csdn.net/luanlouis/article/details/40043991
图解JAVA对象的创建过程:https://www.cnblogs.com/chenyangyao/p/5296807.html
《深入理解Java虚拟机:JVM高级特性与最佳实践》