对象实例化内存布局与访问定位
1. 创建对象的方式:
- new:使用new 关键字创建对象,最常见的方式
- Class 的 newInstance():反射方式,只能调用 public 修饰的空参的构造器
- Constructor 的 newInstance(args):反射方式,可以调用空参、带参的构造器,权限没有要求
- 使用 clone():不调用任何构造器,当前类需要实现 cloneable() 接口
- 使用反序列化
- 第三方库:Objenesis 等
2. 对象创建流程:
- 类加载器首先判断当前对象的类是否加载、链接、初始化
- 为对象分配内存
- 处理并发安全问题:如果开启了TLAB且TLAB足够分配,直接在 TLAB 分配内存,否则采用 CAS机制保证更新的原子性
- 初始化分配到的空间:所有属性设置默认值
- 设置对象的对象头
- 执行对象的 init 方法:初始化代码块,执行构造器
3. 对象的访问定位:对象的访问方式有两种,基于句柄的方式和直接指针的方式
- 基于句柄的方式:堆中额外开辟出一个句柄池,句柄池中的每一个句柄都与堆中的一个对象相关联,栈引用句柄池中的句柄从而间接引用对象,这种好处是堆在发生压缩整理时只改变句柄就可以,栈中的引用不需要变动,坏处是发生了两次引用
- 直接指针的方式:栈直接引用对中的对象,少了一次引用过程,但是堆在发生整理压缩时需要修改栈中的引用指针