原标题:面试官:Object o = new Object() 占用了多少字节?
作者 | 哪儿来的moon 责编 | 张文
头图 | CSDN 下载自视觉中国
来源 | 哪儿来的moon(ID:onetraveller_llxz)
面试的时候,要是面试官问了标题那种问题,你知道怎么解答吗?
本文内容将针对以上面试问题做出解答。
对象的创建过程
以下内容基于 HotSpot VM 分代模型。
这张图其实就能完整的说明一个对象的创建过程到底发生了什么。从左上角开始,一步一步来:
一个对象 new 出来先判断线程栈是否能分配下;
-
如果能分配下,直接分配在栈中。
-
如果分配不下则进行第二步。
如果能分配下,直接分配在栈中。
如果分配不下则进行第二步。
判断该对象是否足够大;
-
如果足够大,则直接进入老年代。
-
如果不够大,则进行第三步。
如果足够大,则直接进入老年代。
如果不够大,则进行第三步。
判断创建对象的线程的 TLAB(本地线程缓冲区)空间是否足够;
-
如果足够,直接分配在 TLAB 中。
-
如果不够,则进入 Eden 区中其他空间。然后进行第四步。
如果足够,直接分配在 TLAB 中。
如果不够,则进入 Eden 区中其他空间。然后进行第四步。
GC 清除;
-
如果清除掉了该对象,则直接结束。
-
如果没有清除掉对象,进行第5步。
如果清除掉了该对象,则直接结束。
如果没有清除掉对象,进行第5步。
此刻对象进入 Survivor 1 区,判断年龄是否足够大;
-
如果年龄足够大,则直接进入 old 区域。
-
如果年龄不够大,则进入 Survivor 2 区,然后进入第4步,循环往复。
如果年龄足够大,则直接进入 old 区域。
如果年龄不够大,则进入 Survivor 2 区,然后进入第4步,循环往复。
通过这张流程图的步骤解析之后,大家应该对一个对象的创建过程有一个相对清晰的思路了。但其实会有很多小细节容易被忽略,这也就是为什么 jvm 会在对象的创建过程中不遗余力的解释,细分多种情况。
为了让大家更深入地理解,我们再来看看下面几个问题:
对象的内存布局
回到文章标题,Object o = new Object;到底占用多少个字节?这道题的目的其实就是考验看你对对象的内存布局了解的是否清晰。先上图:
在 java 中对象的内存布局分为两种情况:非数组对象和数组对象,数组对象和非数组对象的区别就是它需要额外的空间存储数组的长度length。
对象头
对象头又分为 MarkWord 和 Class Pointer 两部分。
- MarkWord:包含一系列的标记位,比如轻量级锁的标记位、偏向锁标记位、gc记录信息等等。在32位系统占4字节,在64位系统中占8字节。
- ClassPointer:用来指向对象对应的Class对象(其对应的元数据对象)的内存地址。在32位系统占4字节,在64位系统中占8字节。
- Length:只在数组对象中存在,用来记录数组的长度,占用4字节。
Interface data
- Interface data:对象实际数据。对象实际数据包括了对象的所有成员变量,其大小由各个成员变量的大小决定。(这里不包括静态成员变量,因为它是在方法区维护的)
Padding
- Padding:Java 对象占用空间是 8 字节对齐的,即所有 Java 对象占用 bytes 数必须是 8 的倍数。这是因为当我们从磁盘中取一个数据时,不会说我想取一个字节就是一个字节,都是按照一块儿一块儿来取的。这一块大小是 8 个字节,所以为了完整,padding 的作用就是补充字节,保证对象是 8 字节的整数倍。
小贴士:moon 在上文特意标注了 32 位系统和 64 位系统不同区域占用空间大小的区别,是因为对象指针在 64 位 JVM 下的寻址更长,所以相比 32 位会多出来更多占用空间。
现在假设一个场景,公司现在项目部署的机器是 32 位的, 老板要让你将项目迁移到 64 位的系统上,但是 64 位系统比 32 位系统需要更多占用空间,应该怎么办?
正常来说我们是不需要这一部分多余空间的,因为 jvm 已经帮你考虑好了,那就是指针压缩。
指针压缩
-XX:+UseCompressedOops 这个参数就是 JVM 提供的解决方案。通过压缩指针,占用的空间就会被压缩为原来的一半,节约空间。classpointer 参数大小就受到其影响。
那么Object o = new Object 到底占用多少个字节?
通过刚才内存布局的学习后,这个问题就很好回答了。面试官其实就是想问你对象的内存布局的理解是怎样的。
我们这里就针对这个问题的结果分析下,这里分两种情况:
- 在开启指针压缩的情况下,markword 占用 8 字节,classpoint 占用 4 字节,Interface data 无数据,总共是12字节,由于对象需要为8的整数倍,Padding 会补充4个字节,总共占用16字节的存储空间。
- 在没有指针压缩的情况下,markword 占用 8 字节,classpoint 占用 8字节,Interface data 无数据,总共是16字节。
了解了对象的创建过程和对象的内存布局,Object o = new Object 占用了多少字节?这类问题就不是难事了!
☞ 告别 Windows、Android,国产操作系统合力破局
☞ 开源吞噬世界,得开发者得天下
☞ 小米 11 发布,售价 3999 元起;罗永浩回应败诉半导体公司;deepin 20.1(1010) 发布|极客头条
☞ 苹果 M1 芯片预示着 RISC-V 完全替代 ARM?
☞ 5G与金融行业融合应用的场景探索
☞带你一文看懂 Blockchain + NoSQL数据库
点分享
点点赞
责任编辑: