Object o=new object()在中占用多少字节?

https://blog.csdn.net/weixin_42864905/article/details/104966716

小姐姐问:Object obj=new Object()ç©¶ç«Ÿå å¤šå°‘å­—èŠ‚å•Šï¼Ÿ

小姐姐问:Object obj=new Object()ç©¶ç«Ÿå å¤šå°‘å­—èŠ‚å•Šï¼Ÿ

Klass Word 这里其实是虚拟机设计的一个oop-klass model模型,这里的OOP是指Ordinary Object Pointer(普通对象指针),看起来像个指针实际上是藏在指针里的对象。而 klass 则包含 元数据和方法信息,用来描述 Java 类。它在64位虚拟机开启压缩指针的环境下占用 32bits 空间。

Mark Word 是我们分析的重点,这里也会设计到锁的相关知识。Mark Word 在64位虚拟机环境下占用 64bits 空间。整个Mark Word的分配有几种情况:

  1. 未锁定(Normal): 哈希码(identity_hashcode)占用31bits,分代年龄(age)占用4 bits,偏向模式(biased_lock)占用1 bits,锁标记(lock)占用2 bits,剩余26bits 未使用(也就是全为0)

  2. 可偏向(Biased): 线程id 占54bits,epoch 占2 bits,分代年龄(age)占用4 bits,偏向模式(biased_lock)占用1 bits,锁标记(lock)占用2 bits,剩余 1bit 未使用。

  3. 轻量锁定(Lightweight Locked): 锁指针占用62bits,锁标记(lock)占用2 bits。

  4. 重量级锁定(Heavyweight Locked):锁指针占用62bits,锁标记(lock)占用2 bits。

  5. GC 标记:标记位占2bits,其余为空(也就是填充0)
    以上就是我们对Java对象头内存模型的解析,只要是Java对象,那么就肯定会包括对象头,也就是说这部分内存占用是避免不了的。所以,在笔者64位虚拟机,Jdk1.8(开启了指针压缩)的环境下,任何一个对象,啥也不做,只要声明一个类,那么它的内存占用就至少是96bits,也就是至少12字节。

内存对齐:4个字节,保证可以被8整除。内存对齐
想要知道为什么虚拟机要填充4个字节,我们需要了解什么是内存对齐?

我们程序员看内存是这样的:

小姐姐问:Object obj=new Object()ç©¶ç«Ÿå å¤šå°‘å­—èŠ‚å•Šï¼Ÿ

上图表示一个坑一个萝卜的内存读取方式。但实际上 CPU 并不会以一个一个字节去读取和写入内存。相反 CPU 读取内存是一块一块读取的,块的大小可以为 2、4、6、8、16 字节等大小。块大小我们称其为内存访问粒度。如下图:

小姐姐问:Object obj=new Object()ç©¶ç«Ÿå å¤šå°‘å­—èŠ‚å•Šï¼Ÿ

假设一个32位平台的 CPU,那它就会以4字节为粒度去读取内存块。那为什么需要内存对齐呢?主要有两个原因:

平台(移植性)原因:不是所有的硬件平台都能够访问任意地址上的任意数据。例如:特定的硬件平台只允许在特定地址获取特定类型的数据,否则会导致异常情况。
性能原因:若访问未对齐的内存,将会导致 CPU 进行两次内存访问,并且要花费额外的时钟周期来处理对齐及运算。而本身就对齐的内存仅需要一次访问就可以完成读取动作。
我用图例来说明 CPU 访问非内存对齐的过程:

小姐姐问:Object obj=new Object()ç©¶ç«Ÿå å¤šå°‘å­—èŠ‚å•Šï¼Ÿ

在上图中,假设CPU 是一次读取4字节,在这个连续的8字节的内存空间中,如果我的数据没有对齐,存储的内存块在地址1,2,3,4中,那CPU的读取就会需要进行两次读取,另外还有额外的计算操作:

  1. CPU 首次读取未对齐地址的第一个内存块,读取 0-3 字节。并移除不需要的字节 0。
  2. CPU 再次读取未对齐地址的第二个内存块,读取 4-7 字节。并移除不需要的字节 5、6、7 字节。
  3. 合并 1-4 字节的数据。
  4. 合并后放入寄存器。

所以,没有进行内存对齐就会导致CPU进行额外的读取操作,并且需要额外的计算。如果做了内存对齐,CPU可以直接从地址0开始读取,一次就读取到想要的数据,不需要进行额外读取操作和运算操作,节省了运行时间。我们用了空间换时间,这就是为什么我们需要内存对齐。

回到Java空对象填充了4个字节的问题,因为原字节头是12字节,64位机器下,内存对齐的话还需要填充4个字节就是128位,也就是16字节

数组:最小是24个字节 8+4+4+4+8

非空对象占用内存计算:TestNotNull的类占用空间是24字节,其中头部占用12字节,变量a是int类型,占用4字节,变量nullObject是引用,占用了4字节,最后填充了4个字节,总共是24个字节,与我们之前的预测一致。但是,因为我们实例化了NullObject,这个对象一会存在于内存中,所以我们还需要加上这个对象的内存占用16字节,那总共就是24bytes+16bytes=40bytes。我们图中最后的统计打印结果也是40字节,所以我们的分析正确。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值