对象实例化过程:
- 加载类元信息
- 为对象分配内存
- 内存规整:指针碰撞 —- 标记压缩
- 内存不规整:虚拟机维护一个列表(通过空闲列表分配,从这些空闲的列表中找到一块足够大的空间划分给对象实例)—- 标记清除
- 处理并发问题
- 采用CAS失败重试、区域加锁保证更新的原子性
- 每个线程预先分配一块TLAB
- 属性的默认初始化(零值初始化)
- 保证对象实例不赋值时可以直接使用
- 设置对象头的信息
- 将对象的所属类(即类的元数据信息)、对象的HashCode和对象的GC信息、锁信息等数据存储在对象的对象头中。这个过程的具体设置方式取决于JVM实现
- 属性的显示初始化、代码块中初始化、构造器中初始化
对象内存布局:
对象头 Header:
- 运行时元数据(Mark Word):
- 哈希值
- GC分代年龄
- 锁状态标志
- 线程持有的锁
- 偏向线程ID
- 偏向时间戳
- 类型指针:
- 指向类元数据InstanceKlass,确定该对象所属的类型
实例数据 Instance Data:
- 说明:对象真正存储的有效信息,包括程序代码中定义的各种类型的字段(包括从父类继承下来的和本身拥有的字段)
- 规则:
- 相同宽度的字段总是被分配在一起
- 父类中定义的变量会出现在子类之前
- 如果CompactFields参数为true(默认为true):子类的窄变量可能插入到父类变量的空隙
对齐填空 Padding:
- 不是必须的,没有特别含义,仅仅起到占位符的作用
对象访问定位:
对象访问的两种方式:
- 句柄访问:
- Java堆中,存在 句柄池 和 实例池。
- 句柄池分为两部分:一部分指向 对象实例数据的指针 另一部分指向 对象类型数据的指针
- Java堆中,存在 句柄池 和 实例池。
- 直接指针:Hotspot使用
- java堆中,直接存放对象实例数据,实例数据中 存放对象类型数据的指针