JVM中对象是如何创建的
在 JVM 中,对象是如何创建的?
如果要回答对象是怎么创建的,我们一般想到的回答是直接 new
出来就行了,这个回答不仅局限于编程中,也融入在我们生活中的方方面面。
但是遇到面试的时候你只回答一个"new 出来就行了"显然是不行的,因为面试更趋向于让你解释当程序执行到 new 这条指令时,它的背后发生了什么。
所以你需要从 JVM 的角度来解释这件事情。
当虚拟机遇到一个 new 指令时(其实就是字节码),首先会去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用所代表的类是否已经被加载、解析和初始化。
因为此时很可能不知道具体的类是什么,所以这里使用的是符号引用。
如果发现这个类没有经过上面类加载的过程,那么就执行相应的类加载过程。
类检查完成后,接下来虚拟机将会为新生对象分配内存,对象所需的大小在类加载完成后便可确定(我会在下面的面试题中介绍)。
分配内存相当于是把一块固定的内存块从堆中划分出来。划分出来之后,虚拟机会将分配到的内存空间都初始化为零值,如果使用了 TLAB
(本地线程分配缓冲),这一项初始化工作可以提前在 TLAB 分配时进行。这一步操作保证了对象实例字段在 Java 代码中可以不赋值就能直接使用。
接下来,Java 虚拟机还会对对象进行必要的设置,比如确定对象是哪个类的实例、对象的 hashcode、对象的 gc 分代年龄信息。这些信息存放在对象的对象头(Object Header)中。
如果上面的工作都做完后,从虚拟机的角度来说,一个新的对象就创建完毕了;但是对于程序员来说,对象创建才刚刚开始,因为构造函数,即 Class 文件中的 <init>()
方法还没有执行,所有字段都为默认的零值。new 指令之后才会执行 <init>()
方法,然后按照程序员的意愿对对象进行初始化,这样一个对象才可能被完整的构造出来。