JUC-Java对象内存布局(对象头,类型指针,自填充)

1. 引入问题

有如下问题:

  1. 请解释一下对象的创建过程
  2. Class对象在堆还是在方法区中
  3. 对象在内存中的存储布局
  4. 对象头具体包括什么
  5. 对象怎么定位
  6. 对象怎么分配
  7. Object obj = new Object(); 在内存中占用多少个字节

2. 堆内存布局

2.1 基于分代的堆的内存布局(复习)

在这里插入图片描述

堆:

  • 年轻代(1)
    • 伊甸园区(8)
    • s0(1)
    • s1(1)
  • 老年代(2)
    (注:元空间在堆外内存中)

2.2 对象在堆中组成部分

在这里插入图片描述
在这里插入图片描述

对象在堆中主要由下面三个部分组成

  • 对象头(Header)
  • 实例数据(Instance Data)
  • 对齐填充(Padding)

其中对象头又分为对象标志(存储对象的基本信息)和类型指针(指向类模板)。

2.3 对象头

2.3.1 对象标志(Mark Word)

对象标志用8字节64位来存储类的一些基本信息。比如:hashcode,GC分代年龄,锁标志等
在这里插入图片描述
注意这里分代年龄是4位。联想之前S区的分代年龄到达了15还没被GC就会到老年区,这里为什么是15?因为底层给了4bit来计算分代年龄。这里的15 = 2 ^ 4 - 1

2.3.2 类型指针(Class Pointer)

Cat object = new Cat();
分析这一句代码各个量的存储位置:

  • new Cat():先在堆空间创建实例对象Cat。
  • object :局部引用变量存放在栈帧中的局部变量表中
  • Cat:类模板(类元数据)存放在方法区(方法区的实现元空间放在堆外内存中)
    类型指针指向他的类模板,通过这个指针来确定该实例对象属于哪个类。

2.3.3 补充:32位CPU和64位CPU区别

32位CPU表示总线的位宽位32位,通过总线来寻址,也就是能够表示2 ^ 32 = 4 * 2 ^ 30 = 4G内存。
同理,64位能够表示8G内存。

2.4 实例数据

如果对象有成员属性,这里就会有数据信息。如果没有属性,就不会有数据信息。比如boolean类型的属性占1个字节。int类型占4个字节。

2.4.1 补充:8中基本数据类型占存储空间的大小。

整数类型:byte(1字节),short(2字节), int(4字节),long(8字节)
浮点类型:float(4字节), double(8字节)
字符类型:char(2字节)
布尔类型: boolean(1个字节)

2.5 对齐填充

2.5.1 为什么要对齐数据?

为了CPU能够高效寻址 。

3. 分析对象占多少个字节

3.1 普通对象

Object object = new Object()占几个字节?
在64位CPU上,对象头中对象标志占8个字节,类型指针占4个字节。实例数据区无数据。对齐区12不是8的倍数了,扩充4个字节变成16。因此一共16个字节。

3.2 数组对象(多了个length)

public static void main(String[] args) {
    int[] a = {1};
    System.out.println(ClassLayout.parseInstance(a).toPrintable());
}

打印的内存布局信息:

在这里插入图片描述
可以看到SIZE一共是24byte。
对象头:对象标志8字节。类型指针4字节。数组长度4字节。
实例数据:int 1 数据4字节。
对齐:前面一共20字节。填充4字节。使其满足8的倍数。

4. 回答开头的问题

  1. 请解释一下对象的创建过程
  • new 申请一块空间,将属性赋值为初始值。(半初始化)
  • 调用构造方法,对变量进行赋值。(初始化)
  • 建立关联:将引用变量指向对象的地址。
  1. 对象在堆还是在方法区中
    对象在堆中。对象所属类的元信息才在方法区中(比如类的方法代码,变量名,方法名,访问权限)。
  2. 对象在内存中的存储布局
    对象创建后存放在堆空间中。一个对象存储结构包括对象头,实例数据,填充空间。对象头中的对象标志用来保存对象的基本信息,比如hascode, 分代年龄,锁标志等信息。对象头中的类型指针指向元空间中的类模板,表示当前对象所属的类。实例数据中存放对象中的属性值。填充字段用于字节对齐使对象存储空间为8的倍数。
  3. 对象头具体包括什么
  • 对象标志:hashcode,锁标志,分代年龄等
  • 类型指针:指向方法区中的类。
  • 数组长度(数组对象才有)
  1. 对象怎么定位
    栈中的局部变量表中的引用变量存放的是对象的地址。通过引用变量能定位到对象。

  2. 对象怎么分配
    如果对象不可逃逸,且属于热点数据,会直接在栈上进行分配。栈上分配的对象不用GC,直接弹出就行了。
    如果对象占用空间很大,直接在老年代分配。
    一般对象会先在年轻代的Eden区进行分配。

  3. Object obj = new Object(); 在内存中占用多少个字节
    在内存中占用16字节,开启与不开启类型指针压缩都是16字节。

5. 参考链接

  1. Java对象的内存布局
  2. 大厂面试题Object object = new Object()
  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值