对象实例化
创建对象的方式
- new
- Class的newInstance()
- Construct的newInstance(Xxx)
- 使用clone()
- 使用反序列化
- 第三方库Objectsis
创建对象的步骤
- 判断对象对应的类是否加载、链接、初始化
- 为对象分配内存
- 如果内存规整-----指针碰撞
- 如果内存不规整-----虚拟机需要维护一个列表,采用空闲列表分配
- 处理并发安全问题:1.采用CAS保证原子性更新 2.每个线程预先分配一块TLAB
- 初始化分配到的空间:所有对象设置默认值,保证对象实例字段在不赋值时可以直接使用
- 设置对象的对象头
- 执行init方法进行初始化
对象的内存布局
对象头:
包括运行时元数据以及类型指针两部分
- 运行时元数据:哈希值、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳
- 类型指针:指向类元数据InstanceKlass,确定该对象所属的类型
注意:若对象是数组,则还需要记录数组的长度。
实例数据
它是对象真正存储的有效信息,包括程序代码中定义的各种类型的字段(包括从父类继承下来的和本身所拥有的字段)
对齐填充
非必须
对象的访问定位
主要是分为两种:句柄访问和直接指针(hotspot采用)
句柄访问
栈中的引用变量指向java堆中句柄池中对应的句柄,每个句柄存储指向对象实例数据的指针(指向堆)和指向对象类型数据的指针(指向方法区)
直接指针
栈中的引用变量指向java堆,堆中存放的是对象类型的指针(指向方法区)和对象实例的数据