Class对象解析

146 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

1 对象的创建过程

  1. class loading
  2. class linking(Verification、Preparation、Resolution)
  3. class Initializing
  4. 申请对象内存
  5. 成员变量赋默认值
  6. 调用构造方法
    1. 成员变量顺序赋初始值
    2. 执行构造方法语句

2 对象在内存中的存储布局

2.1 普通对象

T t = new T();
  1. 对象头:也叫做markword 占用8个字节
  2. ClassPointer指针:class的指针,当class t new出来之后,是属于class T的,会由这个指针指向T.class。当开启-XX:+UseCompressedClassPointers 时为4字节 不开启为8字节
  3. 实例数据:成员变量
  4. Padding对齐,当上边三个总的字节数不为8的倍数时补充到8的倍数

2.2 数组对象

List<int> t = new List()<>;
  1. 对象头:markword
  2. ClassPointer指针:同普通对象
  3. 数组长度:4字节
  4. 数组数据
  5. 对齐 使其总字节数8的倍数

数组对象比普通对象多一个数组长度

3 对象怎么定位

使用句柄访问方式
句柄访问方式,Java堆中会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息。使用句柄方式最大的好处就是reference中存储的是稳定的句柄地址,在对象被移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,而reference本身不需要被修改。
使用直接指针访问方式
Java堆对象的布局就必须考虑如何放置访问类型数据的相关信息,reference中直接存储的就是对象地址。使用直接指针方式最大的好处就是速度更快,他节省了一次指针定位的时间开销
HotSpot使用的是直接指针访问方式

4 class对象头具体包括什么

以32位系统为例: image.png

  • 2位表示锁的状态
  • 1位表示是否偏向锁
  • 4位表示分代年龄,4位的话,最大值为15,所以分代年龄的最大值为15
  • 另有25位存储了对象的hashCode和偏向锁的线程ID等 因为存储对象的hashCode和存储偏向锁线程ID的是同一位置,所以当一个对象计算了hash值之后是无法添加偏向锁的