1、对象的创建流程

① 类加载检查:一般对象创建使用的是 new 关键字,而当虚拟机遇到 new 指令时会检查后面所带的类名(参数)是否可以在常量池中找到一个符号引用,并开始检查这个符号引用所代表的类是否已经被加载、解析、初始化【此处可以对接到类加载机制】。

② 分配内存:类加载检查完毕之后,会为对象在堆中分配内存,这时如果堆中内存是规整的,那么只需要移动指针划分出一块内存即可,此称为指针碰撞;如果堆中内存不是规整的,那么需要一个空闲列表来维护空闲内存信息,以便找到符合对象需求的内存。CMS 理论上使用的是空闲列表的方式,但是里面会维护一个分配缓冲区,在那里进行指针碰撞。这里还需要注意内存分配可能存在线程安全的问题,解决方案是 TLAB(本地线程分配缓冲) +CAS。每个线程会分到一块连续的缓存空间,对象内存预先在线程的本地缓存TLAB中进行,只有当空间不足时才会在堆内存中分配,这时采用的是 CAS+失败重试保证操作的原子性。

③ 初始化零值:对象空间分配完成之后,还需要把这些空间都初始化为零值,这也保证了实例字段可以不赋初始值就使用。

④ 设置对象头:初始化零值之后,为了确认这个对象是哪个类的实例,还需要再对象头中进行相关设置,例如类的元数据信息、哈希码、分代年龄等,如果开启了偏向锁,则对象头会记录下锁偏向的线程信息。

⑤ 运行init方法:上面一系列操作完成之后,对象还需要执行init方法进行初始化工作,完成了这一步对象才算是真正创建了。

2、对象的访问方式

① 使用句柄:这种方式下堆内存中应该有一个句柄池,句柄中包含对象类型数据指针以及对象实例数据指针,此时reference指向的是句柄池中的句柄,间接地可以寻找真正的对象数据;

② 直接指针:这种方式下,reference指向的直接就是对象实例数据,这种方式下少了一次间接引用,但是移动对象时也需要改变reference值;HotSpot 采用这种方式。