对象实例化
创建对象的方式
- new
- Class的newInstance()(反射==>之能调用空参构造器,权限是public )
- Constructor的newInstance(xxx)==>可以空参、带参、权限没有要求
- 使用clone()
- 反序列化:从网络获取对象的二进制流
- 第三方库Objenesls
创建对象的步骤
字节码的角度的创建
从执行角度看(细致分为6个步骤)
- 判断对象对应的类是否加载、链接、初始化
虚拟机接收到一条new的指令,首先去检查这个指令的参数能否在MetaSpace的常量池中定位到一个类的符号引用,并且见这个符号引用是否已经被加载,解析和初始化。如果没有使用类加载器加载
- 为对象分配内存
2.1. 内存模型规整–指针碰撞
2.2 内存模型不规整— 虚拟机维护一个列表 空闲列表分配 - 处理并发问题(采用CAS失败重试,区域佳作保证更新原子性)or (每个线程预先分配一块TLAB)
- 初始化分配到的空间(设置所有属性的默认值,保证对象实例字段在不赋值的时间可以直接调用)
- 设置对象头(将对象所属类(既类的元数据信息)、对象的HashCode和对象的GC信息、锁信息等数据村塾在对象头中)
- 执行init方法进行显示初始化。
对象的内存布局
1.对象头(Header)
运行时元数据(Mark Word)
- 哈希值(HashCode)
- GC分代年龄
- 锁状态标志
- 线程持有的锁
- 面向线程ID
- 偏向时间戳
类型指针
执行元数据Instace Class 确定该对象所属的类型
2.类型数据(Instance Data)
- 相同宽度的字段总是被分配到一起
- 父类中定义的变量会出现子类之前
3. 对象填充(Padding)
占位符