java中创建对象的过程是怎样的

最近在阅读《深入理解JVM》此书,里面讲解了JVM是如何创建对象的,这里写下一篇博客来记录一下。在java里面,创建对象的方式有多种,你可以直接通过new 关键字来创建,你也可以通过反射来创建,可以通过克隆,可以通过序列化等等方式。

那么对象创建的过程是怎样的呢?让我们从JVM的角度来分析,看看。书中写的很详细,这里总结一下,对象的创建大概分为以下几步:

1、检查类是否已经被加载

当JVM遇到一条字节码new 指令时,首先检查该引用指向的类是否能够在常量池中被找到(也就是检查方法区中有没有该类的信息),如果没有,先加载这个类;有的话就执行下一步,为对象分配内存

2、为对象分配内存空间;

类加载检查通过后,接下来虚拟机会为新生对象分配内存。对象需要多大的内存在类加载完成后便可完全确定,为对象分配内存就是把一块确定大小的内存块从堆上划分出来。

分配方式有两种:
1、java堆内存是绝对规整的
java中创建对象的过程是怎样的

假设Java堆中内存是绝对规整的, 所有被使用过的内存都被放在一边, 空闲的内存被放在另一边, 中间放着一个指针作为分界点的指示器, 那所分配内存就仅仅是把那个指针向空闲空间方向挪动一段与对象大小相等的距离, 这种分配方式称为“指针碰撞” 。

2、java堆内存是不规整的
java中创建对象的过程是怎样的

若堆内存不规整,已被使用的内存和空闲的内存相互交错在一起, 那就没有办法简单地进行指针碰撞了, 虚拟机就必须维护一个列表, 记录上哪些内存块是可用的, 在分配的时候从列表中找到一块足够大的空间划分给对象实例, 并更新列表上的记录, 这种分配方式称为“空闲列表”(Free List) 。

选用那种方式来分配内存,取决堆内存分配是否规整。而堆内存是否规整又取决于垃圾收集器。(核心主要是看采用的是那种垃圾回收算法,是否能进行空间压缩整理)

3、为对象字段设置零值;

分配完内存后,需要对对象的字段进行零值初始化(也就是对象的实例数据部分,对象的内存布局被分为三个部分,分别是对象头、实例数据、对齐填充),对象头除外,零值初始化意思就是对对象的字段赋0值,或者null值,这也就解释了为什么这些字段在不需要进程初始化时候就能直接使用

4、设置对象头;

虚拟机需要对这个将要创建出来的对象,进行信息标记,包括是否为新生代/老年代,对象的哈希码,元数据信息,这些标记存放在对象头信息中

5、执行构造方法。

执行对象的构造方法,初始化对象,这样一个对象才算被成功创建。

画一个流程图来帮助记忆一下
java中创建对象的过程是怎样的