这里的对象仅限于普通Java对象,不包括数组和Class对象等,那么对象的创建过程是什么样的呢?
new 指令
当虚拟机遇到一条new指令时,首先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载、解析和初始化过,如果没有的话,将进行类加载过程。
分配内存
当类加载完成后,虚拟机将为新创建的对象分配内存。对象所需要的内存大小将在加载完成后就可以确定(是通过类的元数据信息来确定)。如何来划分内存中的可用空间呢?
(1)如果Java堆中的内存是绝对规整的,所有用过的内存放在一边,没用过的内存放在另一边,中间放着一个指针作为分界点的指示器,分配内存时仅仅把指针往空闲内存空间那边挪动与对象大小的距离即可,这种划分方式称之为“指针碰撞”。
(2)如果内存不是规整的,那么该如何划分内存的呢?虚拟机采用一种叫做“空闲列表”的方式。虚拟机维护一个列表,上面记录着哪些内存是可用的,在分配时就从列表中找到一块足够大的空间划分给对象,并更新表中的记录。
Java堆的是否规整是由所采用的GC是否带有压缩功能来决定的。
除了如何划分内存空间外,还有一个需要考虑的是并发情况下内存分配问题。解决的方案有两种:
(1)对分配内存空间的动作进行同步处理
(2)把内存的分配动作按照线程划分在不同的空间中进行,也就是TLAB(本地线程分配缓冲)方式
内存分配完毕后,虚拟机需要将分配的内存空间都初始化为零(不包括对象头),如果使用TLAB,这一工作可以提前到TLAB分配时进行。
设置对象头
接下来就是对对象头进行必要的设置,如这个对象是哪个类的实例,如何才能找到这些类的元数据信息,对象哈希码等。
init方法
上面的工作完成后,对象已经创建,但是还不能用。执行new指令后,接着调用实例构造器也就是使用invokespecial指令执行init方法,把对象按照程序员的意愿进行初始化。这样真正的对象才算产生出来。
后记
对象创建过程分析就到这里了,错误之处请帮忙指出,大家一起进步。
参考
周志明:《深入理解Java虚拟机》
[朝阳区尼克杨]
转载请注明原创出处,谢谢啦!