array.length是JVM在数组对象头后预留的隐式长度槽,非Java源码定义字段,创建时写入且不可修改,访问通过arraylength指令直接读内存偏移,不经过字段查找或访问控制。

length 是 JVM 注入的隐式字段,不是 Java 源码定义的变量
Java 中的 array.length 并非在任何 class 文件里声明,也不是继承自 Object 或其他类。数组类型(如 [I 表示 int[])由 JVM 在运行时动态生成,不对应用户编写的源码类。JVM 为每个数组对象分配内存时,在对象头之后、元素数据之前,**预留固定字节存储长度值**:32 位 JVM 为 4 字节,64 位 JVM(开启指针压缩)仍为 4 字节,未压缩则为 8 字节。这个值在数组创建瞬间写入,之后不可更改——这正是其“final”语义的底层来源,尽管代码里没写 final 关键字。
访问 length 不经过字段查找,而是直接读内存偏移
字节码指令 arraylength 被 JVM 直接翻译为对上述预留区域的内存读取操作,绕过反射机制、字段解析和访问控制检查:
- 用
getDeclaredFields()查不到 length 字段(返回空数组) - 无法通过
Unsafe安全修改该位置——破坏它会导致后续访问越界或 JVM 校验失败 - 不能覆写、不能继承、不能序列化——它不属于 Java 类型系统中的“字段”概念
与普通对象字段的内存布局有本质区别
以 int[] arr = new int[5] 为例,堆中实际布局为:
- 对象头(12 字节):Mark Word(8B) + Klass Pointer(4B)
- 长度槽(4 字节):值为 5
- 元素区(20 字节):5 个连续 int,各占 4 字节
而普通对象(如 class A { int len; })的 len 是实例字段,位于对象头之后、对齐填充之前,可读可写,受封装和继承约束——length 不是这种意义上的字段。
立即学习“Java免费学习笔记(深入)”;
JVM 多层保障 length 的不可篡改性
长度安全不靠 Java 层修饰符,而依赖 JVM 运行时强制约束:
- 数组创建指令(
newarray/anewarray)只允许写入一次长度 - 所有数组访问指令(
iaload、aastore等)执行前必校验索引范围:0 ≤ index < length - GC 扫描时跳过长度槽(它不是引用类型),避免误判或污染
这种设计让 length 成为真正零开销、高可靠、语义清晰的数组本质属性。


















