Java数组对象在堆内存中比普通对象多一个4字节长度字段,对象头结构相同(Mark Word+Klass Pointer),但数组无实例变量区,元素数据紧随长度字段连续排布,且Klass Pointer指向特殊数组类元数据(如[I、[Ljava.lang.String;)。

Java中数组对象在堆内存中的布局和普通类对象相似,但有关键区别:数组多了一个固定长度字段,且没有实例变量区,元素数据区直接紧随其后。
对象头结构基本一致,但数组额外携带长度信息
两者都包含Mark Word(存储哈希码、锁状态、GC年龄等)和Klass Pointer(指向类型元数据,如[I表示int[],[Ljava.lang.String;表示String[])。不同在于:数组对象头之后立即存放一个4字节的数组长度字段,而普通对象此处是实例变量起始位置。这个长度在创建时确定、不可修改,是JVM识别数组边界的核心依据。
没有实例变量区,元素数据区直接展开
普通Java对象的实例数据区存放类中定义的各个字段(如private String name; private int id;),顺序受字段类型与JVM优化影响;数组则完全跳过这一层——它的“数据”就是元素本身,从长度字段后立即开始连续排布:
- 基本类型数组(如int[]):元素值直接存入,如5个int占20字节(每个4字节)
- 引用类型数组(如String[]):每个槽位存一个对象引用(压缩指针为4字节,非压缩为8字节),不存String对象本体
对齐填充逻辑相同,但整体结构更紧凑
两者都需满足8字节对齐规则(即总大小是8的倍数),不足时插入Padding字节。但由于数组不含分散声明的字段,其内存布局更线性、更可预测:
立即学习“Java免费学习笔记(深入)”;
- 普通对象:对象头 + 实例变量(可能跨类型、有间隙) + Padding
- 数组:对象头 + 长度(4字节) + 元素数据区(严格连续) + Padding(如有需要)
例如new int[3]在64位开启指针压缩的JVM中:对象头12字节(Mark Word 8 + Klass Pointer 4) + 长度4字节 + 数据12字节 = 28字节 → 补4字节Padding → 总32字节。
类型元数据表达方式不同
普通对象的Klass Pointer指向java.lang.Class实例(如Person.class);数组的Klass Pointer指向一个由JVM动态生成的、特殊的数组类元数据,其名称以[开头:
- [I → int[] 类型的运行时类
- [[I → int[][]
- [Ljava.lang.String; → String[]
这种命名约定让JVM能快速区分数组与普通类,并统一支持instanceof、getClass()等操作。


















