解密HotSpot虚拟机中的对象
介绍完class类文件以及它的加载过程,接下来我们看看class类对应的实例对象的秘密。
当虚拟机遇到一条new指令时,首先检查指令后面参数是否能在常量池中对应一个符号引用,然后再检查符号引用对应的class类是否已经加载、解析和初始化过,如果没有则触发该class类的类加载过程(即上一节的《虚拟机加载class文件》)。当类加载检查通过之后,就会给实例对象分配内存空间(一个对象占多大内存空间在类加载完就可以确定的)。分配内存空间有两种可能的情况:
采取那种分配方式要看内存是否规整,而内存是否规整又要看采取的垃圾回收算法是否会把回收的空间compact。(垃圾回收机制之后再说~)
除了考虑分配方式之外,还要考虑的是分配过程是否线程安全。在实际使用中,肯定不止一个线程会触发对象的创建,而不论使用指针碰撞还是空闲列表,分配操作都不是原子操作,所以需要额外的手段来保证线程安全。也有两种方式:
在内存分配完之后,就需要给内存空间都初始化为零值,这样才能保证实例对象没赋值之前就可以使用。
之后就是设置对象头的内容,包含类型元数据信息、对象哈希码等。下文详细介绍对象头。
最终就是执行<init>初始化方法,即程序员的构造器内容了。至此一个对象就创建完成了。
对象在内存中的区域可划分为三块:对象头、实例数据、对齐填充。
对象头中存储了对象的元数据信息。对象头一般可分为两部分:
当对象时数组时,对象头中还需要一块用来记录长度。
实例数据即一个对象所有的实例字段内容,包括父类继承下来的。储存顺序受分配策略和定义的顺序影响。HotSpot默认分配策略是:longs/doubles.ints,shorts/chars,bytes,Booleans,oops(Ordinary Object Pointers)(相同宽度的分配到一起。
填充对齐是为了保证对象大小必须是8字节的整数.
在方法栈中只存了reference类型的数据,即一个对象的引用.这引用如何去定位对象,目前有两种方式.
《深入理解Java虚拟机》读书笔记6-解密HotSpot中的实例对象
原文:https://www.cnblogs.com/wssswjq/p/9880106.html