Java 创建对象
April 12, 2019•121 words
1.创建对象
1.去常量池中找对于类的符号引用--->检查类是否被加载,解析,初始化过
2.进行类加载
3.加载完之后进行对象堆内存分配(大小在类加载完之后就已知),分配根据内存是否规整,分为指针碰撞(就是一个分界线)和空闲列表,规整由 GC 收集器是否压缩决定,Serial,ParNew 是指针碰撞,CMS 为空闲列表
4.处理对象分配时多线程的对象指针,CAS + 重试还有 TLAB
(本地线程分配缓冲)保证每个线程在自己的 TLAB 分配对象
5.对对象分配的区域进行初始化零值,一些默认类型的值
6.设置对象头,包含类的 metadata,对象 GC 分代年龄等
7.执行对象的 init
方法
2.对象内存布局
包含三部分: 对象头,对象实例数据,对齐填充
2.1 对象头
- 第一部分:运行时数据
内容 | 状态 |
---|---|
对象哈希,分代年龄 | 未锁定 |
指向锁记录的指针 | 轻量级锁定 |
指向重量锁指针 | 锁膨胀(重量锁锁定) |
空 | GC 标记 |
偏向线程 ID,时间戳,对象分代年龄 | 可偏向锁 |
- 第二部分:类型指针
对象指向类 metadata 的指针,通过此指针确定对象属于哪一个类实例
2.2 存储对象的内容
包括每个字段的内容,基本类型,oops( ordinary object pointers)
2.3 填充部分
HotSpot VM 内存管理系统要求对象起始地址都是 8 byte 的整数倍。
3.对象访问
java 栈中本地变量表存储一个 reference,通过 reference 来访问对象
- 句柄
堆内维护一个句柄池,reference 指向对象句柄地址,句柄内容如下:
句柄内容 | 指向位置 |
---|---|
到对象实例的数据的指针 | 堆中实例池中的对象实例数据 |
到对象类型数据的指针 | 方法区中对象类型数据 |
- 直接指针
reference 直接指向堆中对象地址,java堆中对象布局包含了类型数据的指针便于访问方法区对象类型数据
HotSpot VM 采用直接指针方式,速度快减少了指针定位。