news 2026/6/10 19:33:51

美团一面:new Object() 在 JVM 中到底占多大内存?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
美团一面:new Object() 在 JVM 中到底占多大内存?

在美团、阿里等大厂的面试中,“一个 Object 对象占多少内存”是一个极其高频的题目。很多候选人认为这是一个考察“背诵能力”的冷门知识,但实际上,它考察的是你对 JVM 内存模型、对象布局以及 CPU 架构的深度理解。今天,我们就来彻底拆解这个看似简单却暗藏玄机的技术点。

一、 为什么我们要纠结这几个字节?

在日常业务开发中,我们很少关注一个对象具体占用了 16 字节还是 24 字节。但在高并发、高吞吐的场景下(如亿级流量的电商大促、海量数据的实时计算),内存就是金钱,内存就是性能

理解对象的内存布局,是进行JVM 调优排查内存溢出(OOM)以及设计高性能缓存组件的基石。

那么,当我们敲下new Object()这行代码时,JVM 堆内存中究竟发生了什么?

二、 庖丁解牛:Java 对象的内存布局

在 HotSpot 虚拟机中,一个对象在内存中的存储布局可以分为三个部分:

  1. 对象头(Header)
  2. 实例数据(Instance Data)
  3. 对齐填充(Padding)

为了更直观地理解,看下图:

1. 对象头(Header)—— 对象的“身份证”

对象头是对象最核心的部分,它包含两类信息:

  • Mark Word(标记字段)
    • 这是对象最“忙碌”的部分。它存储了对象的运行时数据,如:哈希码(HashCode)GC 分代年龄锁状态标志线程持有的锁偏向线程 ID等。

    • 在 64 位虚拟机中,Mark Word 占用8 字节

  • Klass Pointer(类型指针)
    • 对象指向它的类元数据的指针,JVM 通过这个指针来确定这个对象是哪个类的实例。

    • 它的长度取决于是否开启了指针压缩(CompressedOops)。

2. 实例数据(Instance Data)—— 对象的“血肉”

这是对象真正存储有效信息的地方,即我们在代码中定义的各种字段(int, boolean, reference 等)。

  • 对于new Object()来说,因为Object类没有任何字段,所以这部分大小为0

3. 对齐填充(Padding)—— 强迫症的“占位符”

这是最容易被忽视的一点。HotSpot 虚拟机的自动内存管理系统要求对象起始地址必须是 8 字节的整数倍

  • 换句话说,任何对象的大小都必须是 8 的倍数

  • 如果对象头 + 实例数据不是 8 的倍数,JVM 就会用空白数据填充,直到补齐。

三、 深度计算:new Object() 到底多大?

环境假设:我们目前绝大多数服务器都是64 位 JVM。我们将分两种主要情况讨论。

情况 A:64 位 JVM + 开启指针压缩(默认情况)

从 JDK 1.6 update 14 开始,64 位 JVM 默认开启了指针压缩(-XX:+UseCompressedOops)。

  • Mark Word:8 字节
  • Klass Pointer:被压缩为 4 字节
  • 实例数据:0 字节
  • 当前总和:8 + 4 + 0 = 12 字节

注意:12 不是 8 的倍数!

对齐填充:JVM 必须强行填充4 字节,使其达到 16 字节。

结论:16 字节

情况 B:64 位 JVM + 关闭指针压缩

如果你手动设置了-XX:-UseCompressedOops,或者堆内存超过了 32GB(指针压缩会自动失效)。

  • Mark Word:8 字节
  • Klass Pointer:未压缩,占用 8 字节
  • 实例数据:0 字节
  • 当前总和:8 + 8 + 0 = 16 字节

注意:16 已经是 8 的倍数,不需要填充。

结论:还是 16 字节

情况 C:32 位 JVM(古董级环境)

  • Mark Word:4 字节
  • Klass Pointer:4 字节
  • 总计:8 字节

四、 眼见为实:JOL 工具验证

空口无凭,我们使用 OpenJDK 提供的JOL (Java Object Layout)工具来打印对象的内存布局。

引入依赖:

<dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.16</version></dependency>

测试代码:

import org.openjdk.jol.info.ClassLayout;public class ObjectSizeTest {public static void main(String[] args) {Object obj = new Object();// 打印对象布局System.out.println(ClassLayout.parseInstance(obj).toPrintable());}}

控制台输出(JDK 1.8, 64位, 默认开启指针压缩):

java.lang.Object object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)12 4 (loss due to the next object alignment)Instance size: 16 bytesSpace losses: 0 bytes internal + 4 bytes external = 4 bytes total

五、 避坑指南:常见误区

误区 1:指针压缩能减少所有对象的大小?

真相:不一定。 就像new Object(),开启压缩是 8+4+4(填充)=16字节;关闭压缩是 8+8=16字节。对于空对象,指针压缩并没有节省内存空间,只是把“类型指针”占用的空间换成了“填充”空间。但对于包含多个引用字段的复杂对象,指针压缩效果非常显著。

误区 2:数组对象也只占 16 字节?

真相:错误。 数组对象除了对象头,还多了一个4 字节的空间来存储数组长度new int[0]在开启压缩时占用:8(Mark) + 4(Klass) + 4(Length) = 16 字节(正好不需要填充)。

误区 3:所有 CPU 缓存行都是 64 字节?

虽然常见的 x86 架构 CPU 缓存行(Cache Line)通常是 64 字节,这与对象对齐(8 字节)是两个层面的概念。对象对齐是为了让 CPU 无论是读取 32 位还是 64 位数据,都能一次性高效访问,避免跨缓存行读取。

六、 总结与建议

下次面试官问你:“new Object() 占多少内存?”

你可以自信地回答:

“在主流的 64 位 JVM 中,无论是否开启指针压缩,new Object() 都占用 16 字节

区别在于内部结构:

  • 开启压缩:8 字节 Mark Word + 4 字节 Klass Pointer + 4 字节对齐填充。
  • 关闭压缩:8 字节 Mark Word + 8 字节 Klass Pointer。”

💡架构师建议: 在进行海量对象存储设计(如本地缓存、对象池)时,计算内存容量千万不要只算字段大小,对象头和对齐填充的开销(Overhead)往往比你想象的要大得多

https://mp.weixin.qq.com/s/z8d0h-E2wnYggH2An8QR2w

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 14:22:44

Docker中运行Miniconda-Python3.9并安装PyTorch GPU指南

Docker中运行Miniconda-Python3.9并安装PyTorch GPU指南 在深度学习项目日益复杂的今天&#xff0c;环境依赖冲突、GPU资源调度困难、团队协作复现难等问题已经成为工程师和研究人员的日常困扰。一个常见的场景是&#xff1a;本地训练好的模型换到服务器上却因CUDA版本不匹配而…

作者头像 李华
网站建设 2026/6/10 18:09:58

Linux下Miniconda-Python3.9配置PyTorch全流程详解

Linux下Miniconda-Python3.9配置PyTorch全流程详解 在深度学习项目开发中&#xff0c;最令人头疼的往往不是模型设计本身&#xff0c;而是“环境配不起来”——明明代码没问题&#xff0c;却因为Python版本冲突、依赖包不兼容、CUDA驱动错位等问题导致训练失败。这种“在我机器…

作者头像 李华
网站建设 2026/6/10 16:09:15

贪心算法专题(十):维度权衡的艺术——「根据身高重建队列」

哈喽各位&#xff0c;我是前端小L。 欢迎来到贪心算法专题第十篇&#xff01; 想象一下&#xff0c;一群人排队&#xff0c;每个人都知道自己的身高 h&#xff0c;也知道排在自己前面且身高大于或等于自己的人数 k。 现在队伍被打乱了&#xff0c;只给你这两个数字&#xff…

作者头像 李华
网站建设 2026/6/10 14:58:11

PyTorch安装卡顿?切换清华源优化Miniconda-Python3.9下载速度

PyTorch安装卡顿&#xff1f;切换清华源优化Miniconda-Python3.9下载速度 在高校实验室的深夜&#xff0c;你正准备复现一篇顶会论文&#xff0c;环境搭建到一半&#xff0c;conda install pytorch 卡在“Fetching packages”已经十分钟——进度条纹丝不动&#xff0c;网络监控…

作者头像 李华
网站建设 2026/6/9 18:30:07

Docker Events实时事件流:Miniconda-Python3.9监听容器活动

Docker Events实时事件流&#xff1a;Miniconda-Python3.9监听容器活动 在现代云原生架构中&#xff0c;系统的可观测性早已不再局限于日志和指标。随着微服务与容器化部署的深入&#xff0c;对运行时行为的动态感知能力成为运维自动化的关键一环。想象这样一个场景&#xff1a…

作者头像 李华
网站建设 2026/6/10 16:10:47

CTF 赛事 SQL 注入实战手册:绕过过滤机制与非常规注入方法

正文 无过滤带回显的情况 手工注入 bugku的环境 在这一环境中的主要是通过post方式传入一个参数id来查询数据库内容。 首先判断sql语句闭合方式 当在id的值后面加上时&#xff0c;界面无回显&#xff0c;可以判断后端的sql语句应该是 select xxxx from xxxx where id in…

作者头像 李华