创建对象的方式
- 直接new
- 反射
- 克隆
- 反序列化
- 第三方库(如Objenesis)
创建对象步骤
- 判断对象是否以及加载、连接、初始化
- 为对象分配内存
如果规整:指针碰撞(标记压缩)
如果不规整:空闲列表法(标记清除) - 处理并发安全问题
采用CAS失败重试、区域加锁保证更新原子性
每个线程分配一块TLAB - 初始化分配到的空间
属性设置默认值,保证对象实例在不赋值时可以直接使用 - 设置对象的对象头
- 执行init方法进行初始化
对象内存布局
对象头(Header)
运行时元数据
- 哈希值
- GC分代年龄
- 锁状态标志
- 线程持有的锁
- 偏向线程id
- 偏向时间戳
类型指针
指向元数据InstanceKlass,确定该对象所属类型
实例数据
他是对象真正存储的有效信息,包括程序代码中定义的各种类型字段(包括从父类继承下来的和本身拥有的字段)
相同宽度的字段总是分配在一起
父类中定义的变量会出现在子类之前
如果CompactFields参数为true(默认为true):子类的窄变量可能插入到父类变量的空隙
对齐填充
不是必须的,也没有特别含义,仅仅起到占位符作用