Java对象创建过程

170 阅读2分钟

一、类加载检查

当虚拟机遇到new指令的时候,会先检查指令的参数能否在常量池定位到这个类的符号引用,再检查符号引用对应的类是否被加载、解析和初始化过,如果没有,则先进行类加载过程。

二、分配内存

类加载完成后,对象能够确定内存大小,然后在堆中划分出一块内存进行存储。分配的方法有两种,分别是:

    指针碰撞:发生在规整的堆中,该代中采用的垃圾收集器具有压缩整理功能,例如 复制、标记-整理算法。
    空闲列表:发生在不规整的堆中,该代中采用的垃圾收集器不具有压缩整理功能,例如 标记-清理。
    
虚拟机采用那种分配方式取决于jvm堆是否规整,而jum堆是否规整取决于采用的垃圾收集器是否具有压缩整理功能。

内存分配中还需要考虑到一个线程安全问题,虚拟机采用一下两种方法解决:

    CAS+失败重试:CAS是一种乐观锁的表现形式,即不加锁且认为不发生冲突地执行某项工作,一但出现冲突,则会重试,直到成功。
    TLAB:在Eden区中为每一条线程分配内存,当线程创建对象时会分配对应的内存,直到TLAB内存不足以存放新对象或者TLAB内存用完,就会采用CAS+失败重试方法。

三、初始化零值

当内存分配后,虚拟机需要将分配的内存空间设置初始化值,这样的作用是对象的实例字段在Java代码中能够不赋初始值直接使用。(赋的值为对应类型的默认值)

四、设置对象头

初始化零值后,需要对对象进行必要的设置,比如对象是哪个类的实例,如何才能找到对象的元数据信息、对象的哈希码等信息。

五、执行init方法

对虚拟机来说,设置对象头后,对象就已经创建了;而对Java程序来说,还需要执行init方法,把对象按照程序员意愿初始化,才算创建成功。

以上内容可能存在不足或错误,如有发现请指出来。