Java中对象初始化后大小是否固定?技术认知疑问咨询
Java对象初始化后的大小是否固定?
首先明确核心结论:同一类的对象在同一JVM实例、相同运行环境下,初始化后的大小是固定的;但不同类、不同JVM环境下对象大小可能存在差异,而人们常混淆「对象自身大小」与「对象引用指向的其他可变对象大小」,这是认知误区的主要来源。
1. 基础类型固定大小≠对象大小固定
Java基础数据类型(如int占4字节、long占8字节)的大小由JVM规范强制规定,但对象的大小由三部分固定组成:
- 对象头:包含Mark Word(存储哈希码、锁状态等)和类型指针(指向类元数据),大小依赖JVM位数(32位JVM占8字节,64位JVM默认占16字节,开启压缩指针后占12字节)。
- 实例数据:对象中所有字段的总和,基础类型按规范占固定字节,引用类型在64位JVM压缩后占4字节、未压缩占8字节。
- 对齐填充:JVM要求对象大小必须是8字节的倍数,不足时会填充空白字节。
同一类的所有对象,这些组成部分的总和固定不变——因为类的字段结构在编译期就已确定,不会随对象实例变化。
2. 「对象大小不固定」的常见误解来源
- 混淆对象自身与引用指向的对象:比如
ArrayList对象本身的大小固定(仅包含数组引用、当前容量、元素数量等几个字段),但它内部引用的存储数组可以扩容,人们容易把数组的可变大小当成ArrayList自身的大小。 - 不同JVM环境的差异:32位与64位JVM的对象头大小不同,是否开启指针压缩也会影响引用字段的大小,导致同一类对象在不同环境下大小不同,但这是环境差异,并非对象自身大小可变。
- 动态类结构变更:若类在运行时被动态代理或字节码增强(比如新增字段),修改后的类实例大小会变化,但这属于类结构的变更,而非同一类对象初始化后大小改变。
3. 实例验证对象大小固定
定义简单类:
public class User { private int id; private String name; }
在开启指针压缩的64位JVM中,User对象大小计算:
- 对象头:12字节
- 实例数据:
int(4字节) +String引用(4字节)= 8字节 - 对齐填充:12+8=20,不足8的倍数,填充4字节,总大小24字节
所有User实例的大小均为24字节,无论name指向的String对象多大,User自身的大小始终固定。
内容的提问来源于stack exchange,提问作者Htam
相关产品推荐
相关产品推荐

