1 创建对象的步骤

1)判断对象对应的类是否加载、链接和初始化。

2)为对象分配内存,如果内存规整,采用指针碰撞的方式分配内存,如果内存不规整,则使用空闲列表分配。

3)解决并发安全问题:为每个线程分配一个TLAB。

4)初始化分配到的空间。对定义的变量赋初始化值。

5)设置对象的对象头。

6)执行init初始化:显式初始化,代码块初始化,类构造器初始化。

2 内存布局

 

 图1

1)对象头

包含两部分:运行时元数据(hashcode值,GC分代年龄、锁状态标志、线程持有的锁、偏向线程、偏向时间戳);类型指针(指向类元数据,确定该对象所属的类型);如果是数组,还需要记录数组长度。

2)实例数据

是对象真正存储的有效信息,包括程序代码中定义的各种类型的字段;规则:相同宽度的字段总是被分配在一起;父类中定义的变量会出现在子类之前;如果CompactFields参数为true(默认为true;子类的窄变量可能插入到父类变量的空隙)

3)对齐填充

3 对象的访问定位

JVM是如何通过栈帧中的对象引用访问到其内部的对象实例呢?

 

 图2

定位,通过栈上reference访问。

句柄:如图3所示,还需要划分空间用于存储句柄池,也需要先到句柄池,相比直接指针较为麻烦。

 

图3

 

直接指针:如图4所示(Hotspot默认)

 

 

 图4