首页 >> 手游攻略

你的太大了我装不下

各位老铁们,大家好,今天由我来为大家分享你的太大了我装不下,以及对象很大,装不下的相关问题知识,希望对大家有所帮助。如果可以帮助到大家,还望关注收藏下本站,您的支持是我们最大的动力,谢谢大家了哈,下面我们开始吧!

Java对象模型Java数组大小

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

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

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

Java对象模型

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

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

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

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

对象头(Header)对象实例数据(instancedata)对齐填充(Padding)

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

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

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

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

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

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

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

Java数组大小

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

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

接下来我们来看看一维数组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进程中的缓存,对象的内存开销会非常大(通常是真实数据大小的几倍甚至更多)

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



本文由欣欣吧手游攻略栏目发布,感谢您对欣欣吧的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人站长或者朋友圈,但转载请说明文章出处“你的太大了我装不下

标签: