对象内存布局
一、 对象的实例化
1.1 你有几种方式创建对象?
- new
- 反射
- 实现clonable接口,重写clone方法
- 反序列化
- 第三方库Objenesis,利用了asm字节码技术,动态生成Constructor对象
1.2 创建对象的步骤
- 判断对象对应的类是否装载、链接、初始化
- 为对象分配内存
- 指针碰撞
- 空闲列表
- 处理并发安全问题
- 初始化分配到的空间
- 设置对象的对象头
- 执行init方法进行初始化
初始化成员变量,执行实例化代码块,代用类的构造方法,并把堆内对象的首地址赋值给引用变量。
二、对象的内存布局
2.1 对象头(Header)
- 一个是对象自身的运行时元数据(mark word)
- 哈希值
- GC分代年龄
- 锁状态标志
- 线程持有的锁
- 线程偏向ID
- 偏向时间戳
- 另一个是类型指针,指向元数据区的类元数据InstanceKlass,去顶该对象所属的类型
- 如果对象是一个数组,对象头中还必须有一块用于记录数组的长度的数据。
2.2 实例数据(Instace Data)
实例数据部分是对象真正存储的有效信息,即我们在程序代码里面所定义的各种类型的字段内容,无论是从父类继承下来的,还是在子类中定义的字段都必须记录起来。
2.3 对齐填充(Padding)
任何对象的大小都必须是8字节的整数倍。如果对象实例数据部分没有对齐的话,就需要通过对齐填充来补全。
三、对象的访问定位
- 句柄访问
- 直接指针访问