java数组创建时本质是创建堆中对象,栈中仅存null引用;初始化后堆中分配连续内存,基本类型存默认值、引用类型存null;大数组可能直入老年代;长度固定不可变,越界访问抛arrayindexoutofboundsexception。

Java 数组创建时,本质是创建一个对象,因此内存分配遵循 JVM 对象分配规则:数组实例本身存于堆中,而数组变量(引用)存于栈中。
数组声明只是定义引用变量
写 int[] arr; 或 String[] names; 时,JVM 只在栈中分配一个引用类型的变量空间,值为 null。此时尚未在堆中分配任何实际存储空间,也不占用数组元素所需的内存。
- 变量名(如
arr)是栈帧里的局部变量,生命周期随方法调用结束而消失 - 它不指向任何堆内存,不能访问
arr[0],否则抛出NullPointerException
初始化触发堆内存分配
一旦执行 new int[5] 或 {1,2,3} 这类初始化操作,JVM 就会在堆中划分一块连续内存,大小由元素类型和长度共同决定(例如 int[5] 占 20 字节,String[3] 占 3 个引用位宽,约 24 字节)。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 基本类型数组:元素直接存值,如
int[5]默认填 0 - 引用类型数组:元素存
null,不代表对象被创建,只是预留引用槽位 - 数组对象本身有 header(对象头),含哈希码、GC 信息、类型指针等元数据
大数组可能直接进入老年代
数组属于典型的大块连续内存对象。当其大小超过 JVM 预设阈值(如 -XX:PretenureSizeThreshold=1M),JVM 会跳过 Eden 区,直接在老年代分配,避免频繁复制带来的性能损耗。
- 例如
new byte[2_000_000](约 2MB)大概率直入老年代 - 这种策略对缓存、图片像素数组、批量数据处理等场景很关键
- 可通过
jstat或 GC 日志观察分配行为
数组长度固定,不可动态扩容
数组在堆中分配的是固定大小的连续内存块,创建后无法改变长度。所谓“扩容”,实际是新建更大数组、复制旧内容、丢弃原数组——这是 ArrayList 的内部机制,不是数组自身能力。
- 试图访问超出
length的索引(如arr[5]当length==5)会触发ArrayIndexOutOfBoundsException - 数组的
length是 final 字段,只读,不可修改 - 若需动态结构,应选用
ArrayList、LinkedList等集合类
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










