首发于 JavaFamily
<<面向面试官编程>>系列 -- 如何计算 Java 对象大小

<<面向面试官编程>>系列 -- 如何计算 Java 对象大小



0. 前言

面试官: 说一说你平时进行 JVM 调优时如何调整内存大小的?
帅帅: 一般情况下, 我们首先需要分析对象大小, 然后根据...
面试官: 等等, 如何分析对象大小? 对象大小怎么计算?
帅帅: 呃.....
面试官: 今天的面试就到这里, 如果公司有意向会给你电话联系. 请保持电话畅通谢谢. 下一位.

1. Java 对象的内存布局

在 HotSpot 虚拟机中, 对象在内存中存储的布局可以分为三个部分: 对象头(Header), 实例数据(Instance Data)和对齐填充(Padding). 如下图所示.



1.1 对象头

1.1.1 Mark World

对象头包括两部分信息, 第一部分用于存储对象自身的运行时数据, 如哈希码, GC 分代年龄, 锁状态标志, 线程持有锁, 偏向线程 ID, 偏向时间戳等, 这部分数据长度在 32 位 和 64 位虚拟机(未开启指针研压缩)中分别为 4 个字节和 8 个字节, 官方称为 Mark World.
考虑到虚拟机的空间效率, Mark World 被设计成一个非固定的数据结构以便在极小的空间内存储尽量多的信息, 它会根据对象的状态复用自己的存储空间.

Hotspot 虚拟机对象头 Mark World

存储内容标志位状态对象哈希码, 对象分代年龄01未锁定指向锁记录的指针00轻量级锁定指向重量级锁的指针10膨胀(重量级锁定)空, 不需要记录信息11GC 标记偏向线程 ID, 偏向时间戳, 对象分代年龄01可偏向

1.1.2 类型指针

即对象指向它类元数据的指针, 虚拟机通过这个指针来确定这个对象时哪个类的实例. 并不是所有的虚拟机实现都必须在对象数据上保留类型指针, 也就是说, 查找对象的语言数据信息并不一定经过过对象本身.这会在后边博文详细介绍.

1.1.3 数组长度

如果对象是个数组, 那在对象头中还必须有一块用于记录数据长度的数据, 因为虚拟机可以通过普通 Java 对象的元数据信息确定 Java 对象的大小, 但是从数据的元数据中却无法确定数据的大小.

所以, 如果数组长度只有在对象为 Java 数组类型时才会占内存空间.非数组类型的对象, 如 String 对象的数组长度部分大小为 0.

1.2 实例数据

实例数据部分就是对象真正存储有效信息, 也是在程序代码中定义的类型的字段,无论是从父类继承还是自己定义的字段都会被记录, 而存储的顺序会和虚拟机的分配策略参数(FieldsAllocationStyle)和字段在 .java 源码文件中的定义顺序有关.

1.2.1 虚拟机分配策略

从分配策略可以看出, 相同宽度的字段总是被分配到一起. 在满足这个条件的前提下, 父类中定义的字段会出现在子类之前, 如果 CompactFields参数值为 true(默认值), 那么子类之中比较窄的非静态(non-static)基本数据类型变量也可能会插入到父类变量的空隙之中, 以提供内存的利用率.
CompactFields: 假设对象头占用了12个字节,并且再此之后分配的long类型字段不会紧跟在对象头后面分配(long 占 8 个字节, 4 字节不够存),而是在新一个8字节偏移量位置处开始分配,因此对象头和 long 属性之间存在了4字节的空隙,而这个4字节空隙的大小符合(即,大小足以用于)一个 int 属性的内存分配, 所以,int 属性就被插入到了对象头与 long 属性之间了.

1.2.2 Java 基本类型数据大小

类型大小/字节double8long8int4float4short2char2byte1boolean4/1

误区: boolean 只有 true 和 false 两个状态, 一位就够了, 所以 boolean 占用 1 bit? 虽然 Java 虚拟机定义了 boolean 这种数据类型,但是只对它提供了非常有限的支持。在 Java 虚拟机中没有任何供 boolean 值专用的字节码指令,在 Java 语言之中涉及到 boolean 类型值的运算,在编译之后都使用 Java 虚拟机中的 int 数据类型来代替。Java 虚拟机直接支持 boolean 类型的数组,虚拟机的 newarray 指令可以创建这种数组。boolean 的数组类型的访问与修改共用 byte 类型数组的 baload 和 bastore 指令.
Java 虚拟机规范介绍: The boolean data type has only two possible values: true and false. Use this data type for simple flags that track true/false conditions. This data type represents one bit of information, but its "size" isn't something that's precisely defined.
综上所述, 单个boolean型是占4字节(因为编译后会用int来代替), 而boolean数组中的则占1字节(因为用byte来代替的)

1.3 对齐填充

Hotspot VM 的自动内存管理系统要求对象起始地址必须是 8 字节的整数倍, 即就是,对象的大小必须是 8 字节的整数倍, 因此, 当数据不够 8 个字节时就需要通过额外无用的字节来占满 8 字节空间, 这就是对齐填充.对齐填充不仅存在于实例数据部分, 因此当对象头部分没有对齐时, 就需要通过对其填充来补全. 一般情况下, 对象头部分正好都是 8 字节的倍数, 但是有一种情况不是(下面会讲到), 所以, 对象头中也有可能出现对其填充. 而大部分博客/书籍等都只介绍实例数据部分的对齐填充, 其实, 一个对象中是有可能存在两个对齐填充的.
上面的介绍中经常提到一个词: 指针压缩, 这是 JVM 为了节省内存提供的一个机制, 可以通过 VM arguments 配置, 自 JDK 1.6 Update 14之后默认开启. 关于 指针压缩后面会有专门的博文来介绍. 大家可以关注 <<面向面试官编程>>系列的 GitHub 地址: github.com/JavaFamilyCl .来获取最新最全博文.

2. 对象大小的计算

通过对象的内存模型, 大家应该已经猜到如何计算一个对象的大小了, 对, 就是各个部分的大小之和.我们从以下一个案例来看.

2.1 空对象的大小

这里的空对象时指没有任何字段的一个类实例哦!

分析:

结论:







这个时候我想大家应该会有一个疑问了, 开启指针压缩和不开启占用的内存大小都一样啊, 还搞这些干嘛? 别着急, 亲, 继续往后看.

2.2 普通对象的大小

加入一个类有三个字段, int, shortbyte.

这个大小帅帅我就不带大家一起分析了, 留作大家的作业, 大家自行分析, 然后去我刚开通的知识星球留下你的公式和结果, 我来宣布正确答案哦.



2.3 数组对象的大小

如果一个类包含了数组类型的字段该如何计算呢?

分析开启指针压缩:

因此, 含有三个 int 元素的数组对象当开启指针压缩时, 对象大小=8 + 4 + 4 + 12 + 4 = 32 字节



分析未开启指针压缩:





第一节介绍对其填充时我们说, 对象头中也有可能出现对齐填充, 这就是一个例子(可以和面试官好好吹吹, 因为大部分博客/书籍中都值说了实例数据的对齐填充, 比如: <<深入理解 Java 虚拟机第二版>>第 2.3.2 节--对象的内存布局中就没有介绍对象头中的对齐填充).

划重点: 数组对象在未开启指针压缩的情况下存在两段对齐填充.

3. 再谈对齐填充

上面我们谈到了实例数据的对齐填充, 以及对象头的对齐填充,并且得出了一个结论: 数组对象在未开启指针压缩的情况下存在两段对齐填充, 实际上, 并不只有这一种情况才会存在对象头的对齐填充.看一个例子
这是一个复杂对象, 其中包含了一个数组对象和一个 short 对象以及一个 byte 对象.

分析



所以, 对于对齐填充, 应该有以下结论:
无论是否开启对齐填充, 当对象头信息中不够 8 字节整数倍的情况下都会存在对象头对齐填充
如果面试官让你举个例子, 上面帅帅已经给大家了两个例子了, 我觉得足够大家在面试官面前吹一吹了, 哈哈.



如果有任何相关的问题都可以加入 QQ 群一起讨论, 学习, 进步. 此外如果有任何对于本公众号的意见和建议也欢迎大家留言积极批评指正, 最后, 愿你我都能成为更好的自己.



每文一骚


————


However bad life may seem, there is always something you can do, and succeed at.
无论生活有多么糟糕, 你总会找到自己的发光方式.


日常求赞

————

您的三连就是帅帅我深夜撸文的最大的动力, 诚挚的邀请您动动手指头, 转发, 评论, Wow.



关注加好友


拉你进大佬交流群


————————————————







深圳SEO优化公司锦州SEO按效果付费云浮网站设计张掖网站关键词优化推荐玉溪百搜标王推荐永州网站优化广东建设网站定西SEO按天扣费哪家好邢台建网站价格观澜模板推广哪家好宜宾至尊标王报价天津SEO按效果付费价格上海百度竞价包年推广哪家好嘉兴建网站公司荆州关键词排名价格锦州关键词排名公司百色网站改版多少钱平顶山网站改版昌都网站优化按天收费推荐三亚企业网站建设公司徐州网站优化按天计费报价宁波网站制作报价梧州高端网站设计报价民治网站定制价格泰州网站改版银川关键词排名包年推广报价双龙网站定制多少钱红河网站优化排名无锡网站优化报价雅安网站优化排名价格张家口网站推广工具报价歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化