对象的创建
对虚拟机而言,只需要前四步即为完成创建工作,对于进程而言需要执行init方法
- 类加载检查:在常量池定位类的符号引用,确定该类是否被加载、解析、初始化
- 分配内存:从Java堆中划分内存,所需内存在类加载时就已经确定,根据内存是否规整(取决于垃圾收集器是否有压缩整理功能),内存分配方式分为两种:“指针碰撞”和“空闲列表”
ps:分配内存可能引发并发问题,解决方式有两种:
①CAS+失败重试
②给不同线程分配不同的本地线程分配缓冲区,即TLAB,线程在各自的TLAB中不存在并发问题,在为线程分配TLAB时需要加同步锁 - 设默认值:将实例中变量置为默认值,以便于即使没有初始化也能使用
- 配置Header:存储该实例属于哪个类、类的元数据信息、对象的哈希码、GC分代年龄等信息
- 方法:按程序员需要设置变量初始值,成为真正可用的对象
对象的内存布局
- Header:是与数据无关的额外的存储成本,主要存储:①存储对象自身运行时数据(哈希码、GC分代年龄、锁状态信息、线程持有的锁、偏向线程ID、偏向时间戳等)②类型指针(确定该对象是哪个类的实例)③若当前对象为Java数组,则Header中需存储该数组的长度信息
- Instance Data:定义的各种类型的字段
- Padding:占位符,当实例数据长度不达标时占位
对象的访问定位
使用方法栈中的reference类型数据,分为“使用句柄”和“直接指针”两种
- 使用句柄:reference字段指向该对象句柄位置,在Java堆中划分出一块句柄池,每个句柄包含实例数据和类型数据两部分信息,其中类型数据存储在方法区
- 直接指针:reference字段直接指向该对象,优点是访问速度快