Java数组长度不可变的根本原因是其堆内存布局固化:对象头、只读length字段和数据体三部分连续固定,JVM依赖该结构定位数据与边界;扩容实为新建数组+复制元素+引用重定向,而非原地修改。
Java数组长度一旦确定就不可更改,根本原因在于其底层内存结构被JVM严格固化:数组对象在堆中占据一块连续、固定大小的内存区域,包含对象头、length字段和数据体三部分;length是对象头后紧随的只读元数据,不是可写属性。
每个数组对象在堆中实际由三块内容组成:对象头(含GC信息、锁状态等)、4字节length字段、以及紧随其后的原始数据区。JVM靠这个固定偏移来定位数据起始地址和边界——如果允许运行时修改length,就必须重新计算整个对象的内存范围,还可能影响GC扫描、逃逸分析甚至JIT编译优化。这不是设计疏漏,而是用“不可变性”换来的访问效率与内存安全。
频繁创建大数组(如循环中new byte[1024*1024])会快速消耗堆空间,尤其当对象无法及时被GC回收时,容易触发Full GC或直接OOM。更隐蔽的问题是:堆内存本身不保证物理连续,大数组分配失败常因“有足够空闲总和,但无足够连续块”,这和栈溢出机制完全不同。