Redian新闻
>
对象很大,你忍一下

对象很大,你忍一下

公众号新闻

点击上方“芋道源码”,选择“设为星标

管她前浪,还是后浪?

能浪的浪,才是好浪!

每天 10:33 更新文章,每天掉亿点点头发...

源码精品专栏

 
来源:码海

Java 进阶之字节码剖析中我曾经提到这么一段话

int[128][2] ,int[256] 这两个数组看起来一样,但实际上前者比后者多了 246% 的额外开销

针对这句话我收到了几位读者的私信,表示不明白为啥不过一个简单的二维数组会有这么大的开销,本来这个问题在我正在写的类加载机制中有详述,不过文章还没写完(估计本周发),所以我专门抽出这个问题探讨一下,五分钟就能看懂。

Java 对象模型

HotSpot JVM 底层使用名为 oops (Ordinary Object Pointers) 的数据结构来表示对象的对象头

class oopDesc {
  friend class VMStructs;
  private:
    volatile markOop  _mark;
    union _metadata {
      Klass*      _klass;
      narrowKlass _compressed_klass;
    } _metadata;
    ...
}

JVM 每创建一个对象,相当于创建了一个 oopDesc 的对象,即 instanceOopDesc 来表示这个对象,保存在堆中,如下图所示

可以看到 Java 对应主要由以下三部分组成

  • 对象头(Header)
  • 对象实例数据(instance data)
  • 对齐填充(Padding)

其中对象头又包含三个部分

  • markWord:  即 _mark:markOop,用于存储对象运行时的数据,好比 HashCode、锁状态标志、GC分代年龄等。这部分在 64 位操作系统下占 8 字节,32 位操作系统下占 4 字节
  • 指针:指向方法区中的类元数据(类信息)的指针,这部分就涉及到指针压缩的概念,在开启指针压缩的状况下占 4 字节,未开启状况下占 8 字节,默认是开启的
  • 数组长度:这部分只有是数组对象才有,若是非数组对象就没这部分。这部分占 4 字节。

除此之外对象还有两个部分值得我们注意

  • 对象实例数据(instanceData): 用于存储对象中的各种类型的字段信息(包括从父类继承来的)
  • 对齐填充:Java 对象大小默认按 8 字节对齐的,如果「对象头」+「对象实际数据」不足8的位数,对齐填充会补齐相应的字节以让对象大小达到 8 的倍数

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

Java 数组大小

知道了对象模型的表示,再来看数组的大小,首先必须明确两点

  1. 在 Java 中数组是一种特殊的对象(也是对象,也有对象头)
  2. 一个多维数组是一个简单数组的数组,  例如,一个二维数组的每一行都是一个独立的数组对象

接下来我们来看看一维数组 int[256]  在内存中有多大,一维数组其实可以认为是普通的对象,首先对象头可以知道是 8(markword) + 4(kclass) + 4(数组长度)= 16 字节,对象实际数据大小为 256 * 4(int 大小为 4 个字节) = 1024  字节,所以此时总的字节数为 16 + 1024 = 1040 字节,是 8 的位数(1040/8 = 130),所以 padding 为 0, 也就是说 int[256] 一维数组的字节大小为 1040 字节

再来看一下二维数组 int[128][2] 的大小,我们知道在 C 语言中二维数组(事实上是任何多维数组)本质上是一维数组通过指针操作来实现的,但在 Java 中多维数组是由一系列的嵌套数组组成,也就是说对于二维数组而言,每一行(int[0][…],int[1][…],…,int[127][…])都对应一个数组对象,都需要额外的开销,一图胜千言,如下所示

先来看左边的对象大小:

数组的每一行 int[0],int[1],..int[127] 其实都是指向数组的指针,为 4 个字节,所以左边对象占用空间大小为 16 + 4 * 128 = 528,是 8 的倍数(528/8 = 66),所以 padding 为 0,所以总大小为 528

再来看左边的 int[0] 等指向的数组对象大小:

由于左边每个行数组的指向都指向了两个元素的数组(int[x][0],int[x][1]),它们的对象大小为  16 + 4 + 4 = 24,是 8 的倍数,所以 padding 为 0 ,而总共有 128 个这样的对象,所以右边总的对象大小为 128 * 24 = 3072

由此可知 int[128][2] 对象大小为 528 + 3072 = 3600 字节,比一维数组 int[256](1024 字节)多了 246% !

上述计算的是否正确呢,我们可以用 JDK 自带的 ObjectSizeCalculator 来计算一下,如下:

与我们的计算结果完全一致!

其实不光是二维数组,包括字节串,普通的对象开销也一般会比对象实际数据大几倍,到此我相信你不难明白上一篇中开头这样一段话的含义了:kafka 中为啥要使用 pageCache 了, 因为如果不用页缓存,而是用 JVM 进程中的缓存,对象的内存开销会非常大(通常是真实数据大小的几倍甚至更多)



欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢

已在知识星球更新源码解析如下:

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。

谢谢支持哟 (*^__^*)

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
拜登预告中美下一步,中国回应信息量很大……赠书 | 这7本书,让你忍不住一口气读完!贵州一客栈凌晨发生火灾,9人遇难!目击者:火势很大,一下冲起10多米术后疼痛要及时采取镇痛措施,忍一时可能演变为终生慢性疼痛!信息量很大!欧洲议会新冠肺炎峰会完整版给我5分钟,你的分析图还能再抢救一下!真想锤爆日本的头!这次对中国的影响很大,必须打击到底!信息量很大,华为刊发任正非最新内部讲话全文!文革 - 血色,但不浪漫基辛格最新专访,信息量很大(下)不争不抢的汤唯却在戛纳红毯赢很大看《奥本海默》前,你真得了解一下他普京终于宣布!这是一盘很大的局!为啥阅读量很大,语文考试却很差?唉,你不看娃读的都是啥书呀……世界唯一、日本第一的高尔夫观音菩萨你们会选择安逸但是工资低的工作还是压力很大但是回报高的工作?注意,超级英雄天团登陆加拿大,夏日炎炎,你 pick 谁?骨科专家:它比跑步更毁膝盖!危害极大,你却天天在做…希腊游记:中学老师讲错了吗咀外文嚼汉字(241)“借金渍”,日本借钱谚语陈道明:人到中年,本事再大,你都争不过天道(深度好文)小学成绩有很大的欺骗性,很多高分孩子到了初中就会掉队,是真的吗?我是个鸭,你忍一下化妆不化妆差别很大,现在有点自卑不敢谈恋爱...冰岛Kirkjufellsfoss,热点风景​上海交大,你的吃相何必想那么难看?有本事,你动一下试试!猫爪必须在上!等一下,你是不是玩不起有一个非常“抠门”的对象,你该怎么办?剑桥大学学术活动资料包!48页,信息量很大,申请必备!姚洋:这里我要批评一下美国人,你们太"浪漫"了一口爆浆,猫山王榴莲冰粽,一年只卖十几天,礼盒送人很大气!A股重磅!证监会刚刚发声,信息量很大!四大秋招经验盘点:进入四大,你需要过多少关?有些女人潜力很大,尤其是离婚后......
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。