您的位置 首页 > 清洁清洗

你的太大我的装不下(对象很大)

大家好,今天来为大家分享你的太大我的装不下的一些知识点,和对象很大的问题解析,大家要是都明白,那么可以忽略,如果不太清楚的话可以看看本篇文章,相信很大概率可以解决您的问题,接下来我们就一起来看看吧!

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

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

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

4、HotSpotJVM底层使用名为oops(OrdinaryObjectPointers)的数据结构来表示对象的对象头

5、classoopDesc{\nfriendclassVMStructs;\nprivate:\nvolatilemarkOop_mark;\nunion_metadata{\nKlass*_klass;\nnarrowKlass_compressed_klass;\n}_metadata;\n...\n}\n

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

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

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

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

9、项目地址:https://github.com/YunaiV/ruoyi-vue-pro

10、视频教程:https://doc.iocoder.cn/video/

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

12、接下来我们来看看一维数组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字节

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

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

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

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

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

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

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

你的太大我的装不下和对象很大的问题分享结束啦,以上的文章解决了您的问题吗?欢迎您下次再来哦!

本站涵盖的内容、图片、视频等数据,部分未能与原作者取得联系。若涉及版权问题,请及时通知我们并提供相关证明材料,我们将及时予以删除!谢谢大家的理解与支持!

Copyright © 2023