1. 问题背景与核心概念
在Java面试中,对象内存占用是一个经典问题。当面试官问"new Object()在JVM中占多大内存"时,他们实际上在考察你对JVM内存模型的深入理解。这个问题看似简单,但涉及指针压缩、对象头、内存对齐等多个关键技术点。
我们先明确几个基本概念:
- 在32位JVM中,一个普通引用占4字节
- 在64位JVM中,一个普通引用占8字节
- 开启指针压缩(-XX:+UseCompressedOops)后,64位JVM中的引用会降为4字节
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 对象内存结构解析
一个Java对象在堆内存中的存储布局可以分为三个部分:
2.1 对象头(Mark Word)
对象头包含两类信息:
- Mark Word:存储对象自身的运行时数据
- 哈希码(HashCode)
- GC分代年龄
- 锁状态标志
- 线程持有的锁
- 偏向线程ID等
在64位JVM中,Mark Word占8字节(不考虑压缩)
2.2 类型指针(Klass Pointer)
指向对象元数据的指针,JVM通过这个指针确定对象是哪个类的实例。
在64位JVM中:
- 未压缩:8字节
- 压缩后:4字节
2.3 实例数据(Instance Data)
存储对象真正的有效信息,即我们在代码里定义的各种字段内容。对于Object类,这部分为空。
2.4 对齐填充(Padding)
HotSpot VM要求对象起始地址必须是8字节的整数倍,因此当对象大小不是8的倍数时,需要对齐填充。
3. 具体计算过程
让我们计算一个最简单的Object对象在64位JVM中的内存占用:
- 对象头:8字节(Mark Word)
- 类型指针:
- 未压缩:8字节
- 压缩后:4字节
- 实例数据:0字节(Object类无实例字段)
- 对齐填充:
- 未压缩:8 + 8 = 16字节(已是8的倍数,无需填充)
- 压缩后:8 + 4 = 12字节 → 需要填充到16字节
因此:
- 关闭指针压缩:16字节
- 开启指针压缩:16字节(其中4字节是填充)
4. 验证方法
我们可以使用JOL(Java Object Layout)工具来验证这个结论:
code复制
