JVM—HotSpot虚拟机探秘

时间:2023-01-02 12:13:27

一.对象的创建

  1. 执行new指令:常量池查能否查到类的符号引用 并且检查该符号引用代表的类是否被加载、解析和初始化过,若没有执行类加载
  2. 新生对象分配内存:java堆中划分指定大小(类加载完可以完全确定)的内存给新生对象,若java堆内存完全规整,使用指针碰撞(指针往空闲区偏移),若不规整采用空闲列表(虚拟机维护的一个列表,记录上哪些内存块是可以用的)。内存规整判断依据,垃圾收集器是否带有内存压缩整理功能。
  3. 分配内存并发冲突解决方案:一种是同步处理,虚拟机采用CAS配上失败重试的方式保证更新的原子性;另外一种是每个线程在java堆中预先分配一小块内存(TLAB本地线程分配缓冲),先在各自的TLAB上分配,等TLAB用完了并分配新的TLAB,才需要同步锁定。-XX:+/-UseTLAB,设置是否用TLAB。
    1. 内存分配完成后,将分配到的内存初始化为零值(不包括对象头),如果使用TLAB也可以将该操作提前到分配TLAB时,这样做的意义能够保证实例对象字段不赋初始值就可以使用(对应类型的零值)。
    2. 虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对
      象的哈希码、对象的GC分代年龄等信息。这些信息存放在对象的对象头(Object Header)之中。根据虚拟机当前的运行状态的不同,如是否启用偏向锁等,对象头会有不同的设置方式。

在上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了,但从Java程序的视角来看,对象创建才刚刚开始——<init>方法还没有执行,所有的字段都还为零。所以,一般来说(由字节码中是否跟随invokespecial指令所决定),执行new指令之后会接着执行<init>方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全产生出来。