对象占用多少内存?

3 篇文章 0 订阅
1 篇文章 0 订阅

背景

看h2源码的过程中,由于每个Page需要持久化,便使用一个字段存放写入文件时占用的字节大小,而我对java对象占用字节大小不甚清晰,便查找资料记录如下:

java对象在堆中如何存放

java对象在堆中分为三个部分,分别是 对象头(Header),实例数据(Instance Data)和对齐填充(Padding)

对象头

分为三个字段:

  • mark
  1. 8个字节
  • klass
  1. 4个字节(32位JVM或64位JVM开启指针压缩)
  2. 8个字节(64位JVM且关闭指针压缩)
  3. 指向instanceklass
  • length
  1. 4个字节
  2. 只有数组对象会有此值,表示数组的长度

存储了Java对象hash、GC年龄、锁标记、class指针、数组长度等信息

实例数据

当前对象中的实例字段。由基本数据类型和引用类型组成的。

 

对象填充

VM要求对象大小须是8的整体数,该部分是为了让整体对象在内存中的地址空间大小达到8的整数倍而额外占用的字节数。

压缩指针

  1. 32位HotSpot VM是不支持UseCompressedOops参数的,只有64位HotSpot VM才支持。
  2. 可通过-XX:+UseCompressedOops-XX:-UseCompressedOops进行开启和关闭
  3. java7和java8默认开启

为什么用压缩指针?

  1. 4字节只能寻址到4G内存,不足;8字节可以寻址到232*4G内存,太多了
  2. 使用8bit表示oop( ordinary object pointer,一般对象指针),相较于4bit而言,会使所有应用程序运行时占用的空间大1.5倍
  3. 增加了GC开销
  4. 降低CPU缓存命中率

压缩指针原理

  1. 确保所有的对象都是8bit对齐
  2. oop指向的地址只需要保存对象的起始位置即可,没必要寻址到8bit的每一位,那么oop指向的地址的后三位全是000,可以省略,也即oop可以表示 前32位+000 ,一共35位的地址,即23*4G=32G的内存

信息是否被压缩?

哪些信息会被压缩?

  1. 对象的全局静态变量(即类属性)
  2. 对象头信息:64位平台下,原生对象头大小为16字节,压缩后为12字节
  3. 对象的引用类型:64位平台下,引用类型本身大小为8字节,压缩后为4字节
  4. 对象数组类型:64位平台下,数组类型本身大小为24字节,压缩后16字节

哪些信息不会被压缩?

  1. 指向非Heap的对象指针
  2. 局部变量、传参、返回值、NULL指针

展望

  1. 所有对象16bit对齐,压缩指针可以表示64G内存(也可以此类推)
  2. 5字节oop,可以表示1024G内存;6字节oop,可以表示65536*4G内存
  3. 变长oop

总结

对象头大小

开启指针压缩

关闭指针压缩

是数组对象

16byte

20byte

不是数组对象

12byte

16byte

更多知识请戳

java开发实习工程师

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值