当前位置: 首页 > news >正文

基础篇八 一个空 Object 啥都没干,凭什么占了 16 字节内存?

文章目录

    • 一、先给你答案:16 字节
    • 二、逐项拆解:16 字节花在了哪?
      • 第一笔:Mark Word —— 8 字节的"身份证 + 体检报告"
      • 第二笔:Klass Pointer —— 4 字节的"户口本"
      • 第三笔:对齐填充 —— 4 字节的"凑整费"
    • 三、换个配置,结果不一样
    • 四、加了属性会怎样?
    • 五、数组对象呢?多了个"长度"
    • 六、自己动手验证:用 JOL 量一量
    • 七、回到全貌:一张图记住
    • 八、回答技巧与点评
      • 标准回答
      • 加分回答
      • 面试官点评

个人网站

你写了一万次new Object(),但你有没有认真想过:这个对象里面啥都没有,它到底占多大内存?

我第一次被问到这个问题的时候,随口说了句"8 字节吧",面试官微微一笑,我就知道——坏了。后来我花了一下午把这事搞明白,才发现答案比我想的有趣得多。今天跟你聊聊,一个空 Object 到底凭啥占了 16 字节。

一、先给你答案:16 字节

在 64 位 JDK、默认配置下,一个new Object()16 字节

但诡异的是——你写的属性占了 0 字节。16 字节全是 JVM 自己塞进去的"基础设施"。

来,我们把 Object 拆开看看钱都花在哪了:

┌────────────────────────────────────┐ │ Object 内存布局 │ ├──────────────┬──────────┬──────────┤ │ Mark Word │ Klass │ Padding │ │ (8 字节) │ Pointer │ (4 字节) │ │ │ (4 字节) │ │ ├──────────────┼──────────┼──────────┤ │ 你的数据 │ │ │ │ (0 字节) │ │ │ └──────────────┴──────────┴──────────┘ 8 + 4 + 0 = 12 → 对齐到 16 字节

就像你租了个 16 平的房间,自己啥家具都没放,结果全被物业的设备占了——水电表、门禁卡、消防器材,一个都少不了。

二、逐项拆解:16 字节花在了哪?

第一笔:Mark Word —— 8 字节的"身份证 + 体检报告"

每个对象都有一个 Mark Word,里面存的是 JVM 运行时最要紧的信息:

存储内容说白了是啥
HashCode对象的身份证号
GC 分代年龄这对象熬过了几次垃圾回收
锁状态标志当前有没有人锁住它
偏向线程 ID最近谁老用它

而且 Mark Word 是复用设计的——不同状态下,存的字段不一样。就像一块可擦写的白板,无锁时写哈希码,加锁了就写锁信息:

无锁状态: ┌─────────────────────────────────────────────┐ │ HashCode (25bit) │ GC年龄(4bit) │ 0 │ 01 │ └─────────────────────────────────────────────┘ 偏向锁状态: ┌─────────────────────────────────────────────┐ │ 线程ID (54bit) │ GC年龄(4bit) │ 1 │ 01 │ └─────────────────────────────────────────────┘ 轻量级锁: ┌─────────────────────────────────────────────┐ │ 指向锁记录的指针 (62bit) │ 00 │ └─────────────────────────────────────────────┘ 重量级锁: ┌─────────────────────────────────────────────┐ │ 指向 Monitor 的指针 (62bit) │ 10 │ └─────────────────────────────────────────────┘

下次面试官问 synchronized 的锁信息存在哪,你可以拍着桌子说:Mark Word!

第二笔:Klass Pointer —— 4 字节的"户口本"

这个指针指向方法区里的类元数据,告诉 JVM:“我是Object的实例,不是String,别搞混了。”

那为什么是 4 字节而不是 8 字节?因为 JVM 默认开了指针压缩(Compressed Oops)。

什么意思呢?打个比方:你住在一个小区,门牌号本来需要 8 位数字才够用,但这个小区不大,4 位数字就能给所有房子编号了——那当然用 4 位更省事。

JVM 也是这个逻辑:堆内存小于 32GB 时,4 字节就够寻址了,没必要浪费 8 字节。

配置Klass Pointer条件
压缩开启(默认)4 字节堆 < 32GB
压缩关闭8 字节堆 ≥ 32GB

第三笔:对齐填充 —— 4 字节的"凑整费"

8 + 4 = 12,不是 8 的倍数。JVM 要求对象大小必须是 8 的倍数,所以补 4 字节 padding 凑到 16。

为啥非要凑整?因为 CPU 从内存读数据是按块来的(一个缓存行 64 字节),如果对象没对齐,一个字段可能横跨两块,得读两次才能拼出来——太慢了。对齐后保证字段不跨块,一次读完。

这笔"凑整费"其实挺划算的——4 字节换来了更快的内存访问速度。

三、换个配置,结果不一样

场景Mark WordKlass Ptr你的数据Padding总计
64 位 + 压缩(默认)840416
64 位 + 不压缩880016
32 位 JVM44008

32 位只要 8 字节,但现在基本没人用了。64 位不压缩时 Klass Pointer 变 8 字节,8+8=16 刚好对齐,不用补 padding——巧了,结果还是 16。

四、加了属性会怎样?

classMyObject{inta;// 4 字节byteb;// 1 字节longc;// 8 字节}

内存布局(64 位 + 压缩):

┌──────────┬──────────┬────┬────┬──────┬──────┐ │Mark Word │Klass Ptr │ a │ b │ pad │ c │ │ 8 字节 │ 4 字节 │4字节│1字节│3字节 │8字节 │ └──────────┴──────────┴────┴────┴──────┴──────┘ 总计:8 + 4 + 4 + 1 + 3 + 8 = 28 → 对齐到 32 字节

你注意到没?byte blong c之间多了 3 字节 padding。因为 JVM 会把字段重新排序——先放大的(long 8 字节需要 8 对齐),小的塞缝隙。byte b后面补 3 字节,让long c从 8 的倍数位置开始。

这就像搬家师傅摆家具:大衣柜必须靠墙对齐放,小箱子见缝插针。

五、数组对象呢?多了个"长度"

int[]arr=newint[0];// 空数组

数组比普通对象多一个length字段(4 字节):

┌──────────┬──────────┬────────┐ │Mark Word │Klass Ptr │ length │ │ 8 字节 │ 4 字节 │ 4 字节 │ └──────────┴──────────┴────────┘ 总计:8 + 4 + 4 = 16 字节

一个元素都没有,也占 16 字节——对象头和长度字段省不了。

六、自己动手验证:用 JOL 量一量

光听我说你肯定不信,自己量!JOL(Java Object Layout)是 OpenJDK 出的测量工具:

<dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.17</version></dependency>
importorg.openjdk.jol.info.ClassLayout;Objectobj=newObject();System.out.println(ClassLayout.parseInstance(obj).toPrintable());

输出:

java.lang.Object object internals: OFF SZ TYPE DESCRIPTION VALUE 0 8 (object header: mark) 0x0000000000000001 8 4 (object header: class) 0x00001000 12 4 (object alignment/padding) Instance size: 16 bytes

12 字节有效数据 + 4 字节对齐 = 16 字节,和我们分析的完全一致。

七、回到全貌:一张图记住

对象 = 对象头 + 实例数据 + 对齐填充 对象头 = Mark Word + Klass Pointer(+ 数组长度) │ │ │ └─ 4字节(压缩)/ 8字节(不压缩) └─ 固定 8 字节 实例数据 = 你的字段(JVM 可能重排序) 对齐填充 = 凑到 8 的倍数 空 Object: 8 + 4 + 0 + 4 = 16 字节 空 int[]: 8 + 4 + 4 + 0 = 16 字节

八、回答技巧与点评

标准回答

64 位 JVM 默认配置下,一个空的 Object 对象占 16 字节。其中 Mark Word 占 8 字节,存储哈希码、GC 分代年龄、锁状态等运行时信息;Klass Pointer 占 4 字节(指针压缩开启),指向类元数据;实例数据 0 字节;对齐填充 4 字节,凑到 8 的倍数。

加分回答

如果你能接着说出以下几点,面试官会眼前一亮:

  1. 提到指针压缩:默认开启 Compressed Oops,Klass Pointer 是 4 字节而不是 8 字节,条件是堆内存小于 32GB
  2. 提到对齐原因:8 字节对齐是为了配合 CPU 缓存行读取,避免字段跨缓存行导致二次读取;同时为指针压缩提供基础(地址低 3 位恒为 0)
  3. 提到验证方式:用 JOL 工具可以直接打印对象内存布局,自己跑一遍比背答案靠谱

面试官点评

这道题考察的不是你背没背 16 这个数字,而是看你是否理解对象的内存结构。能说出 Mark Word 和 Klass Pointer 的人不少,但能说清"为什么是 4 字节而不是 8 字节"(指针压缩)、"为什么需要对齐"的人就不多了。如果你还能提到 JOL 工具验证,说明你真的是动手验证过,不是死记硬背的——这在面试中是非常加分的。

原文阅读


内容有帮助?点赞、收藏、关注三连!评论区等你 💪

http://www.jsqmd.com/news/675905/

相关文章:

  • 2026年靠谱的易道大咖推荐,多维度分析其口碑与专业度哪家好 - myqiye
  • Thorium Reader深度解析:如何通过跨平台架构打造专业级电子书阅读体验
  • Windows 10下Detectron2安装踩坑记:nvcc.exe报错终极解决与CUDA 10.2环境配置详解
  • 盒马鲜生购物卡回收最新流程,一分钟搞定! - 团团收购物卡回收
  • P1396题解
  • PyTorch 2.8镜像快速部署:RTX 4090D 24G显存下5分钟启动WebUI视频生成界面
  • 如何配置Oracle环境变量_ORACLE_HOME与PATH路径映射
  • 分享袋装物料全自动拆垛机品牌推荐,智能化程度你了解多少 - 工业品牌热点
  • Grok Chat Completion API 的应用与使用
  • 从 ModuleNotFoundError 到成功安装:flash_attn 依赖缺失的排查与修复指南
  • 工业级与民用怎么选?驰尔达对讲机全系列硬核选购指南 - 速递信息
  • claude.exe 与你运行的 Windows 版本不兼容。请查看计算机的系统信息,然后联系软件发布者。问题的解决方法
  • 百万级数据怎么爬?我用ddddocr+OpenCV搞定Beckett签名认证网站的验证码
  • 5分钟掌握:华为设备Bootloader终极解锁指南
  • 盘点2026年有实力的本地成人函授正规校外教学点推荐,看完再选 - 工业品网
  • 盒马购物卡回收全攻略,教你轻松回血! - 团团收购物卡回收
  • 用旧投影仪和摄像头DIY结构光扫描仪:3D Scanning Software实战与点云效果展示
  • vLLM生产部署指南2026:高并发LLM推理系统的工程实践
  • QT字符串处理避坑指南:为什么你的toHex()转换结果不对?
  • 抖音批量下载工具终极指南:如何高效获取去水印视频素材
  • 从零组装电赛送药小车:OpenMV视觉核心+STM32控制,我的软硬件联调全记录
  • 分享2026橡胶辊规格定制、快速定制服务,推荐靠谱厂商 - mypinpai
  • WSL2里用snap装软件总报错?别慌,可能是systemd没开(附Ubuntu 20.04配置详解)
  • Spring Boot 3.x + weixin-java-miniapp 4.1.0:5分钟搞定小程序登录与手机号获取(附完整代码)
  • 2026年铝合金防静电地板定制实力榜:江苏中天实力与品质双优 - 江苏中天庄美荃
  • 别再滥用单例了!在Unity中实现一个轻量级、可测试的事件总线(Event Bus)系统
  • 宁夏做AI搜索推广选哪家?优选宁夏壹山网络_本地自营,定制方案、全行业适配 - 宁夏壹山网络
  • AI专著写作新突破!AI写专著工具,快速产出20万字高质量专著!
  • 2026 支持 2.5D 与存储行业的国产芯片封装设计软件推荐 - 品牌2026
  • 告别重启!用VirtualBox 6.1直接挂载Batocera游戏U盘,办公摸鱼无缝切换