ArrayList的扩容源码分析
各位看官,大家早安午安晚安呀~~~
如果您觉得这篇文章对您有帮助的话
欢迎您一键三连,小编尽全力做到更好
欢迎您分享给更多人哦
今天我们来学习:ArrayList的扩容源码分析
1.几个关键定义
1.表示 当前操作需要的最小容量
2.Integer.MAX_VALUE3 .初始容量:惰性初始化:默认构造的
ArrayList
初始用空数组标记,首次添加时才真正分配空间(节省内存)
4.扩容规则:当添加元素时发现容量不足,会按照 当前容量 * 1.5 的方式进行扩容(一般是这个) 或者 扩容到minCapacity:表示 当前操作需要的最小容量 或者……………… (下面源码我会讲解)
2.源码全面解析:
首先判断当前操作需要的最小容量 是否已经超过数组容量. 如果 > = 就扩容
问题:
3.超过限制的情况
超过 MAX_ARRAY_SIZE:ArrayList 会尝试扩容到
Integer.MAX_VALUE
超过 Integer.MAX_VALUE:
如果所需容量计算时发生整数溢出(变成负数),会抛出
OutOfMemoryError
如果正好需要
Integer.MAX_VALUE
,可以成功分配(理论上的极限)4. 实际限制
在实践中,由于数组本身有对象头开销,加上 JVM 实现限制,通常无法真正分配接近
Integer.MAX_VALUE
大小的数组。尝试分配超大数组通常会先因内存不足而失败。
5. 为啥是 Interger.MAX_VALUE - 8 ?
其实是因为对象头的存在,
对象头(对象的元信息)的内存开销
Java 中每个对象(包括数组)都有一个对象头,包含以下部分(以 64 位 JVM 为例):
Mark Word(8 字节):
存储对象的哈希码、锁状态、GC 分代年龄等信息
在 32 位 JVM 中是 4 字节
Klass Pointer(通常 8 字节,但可能压缩为 4 字节):
指向对象类元数据的指针
开启压缩指针(-XX:+UseCompressedOops)时为 4 字节
数组长度(仅数组有,4 字节):
记录数组长度的 int 字段
总开销:
普通对象:8-16 字节(Mark + Klass)
数组对象:12-16 字节(Mark + Klass + 数组长度)
6.总结:这样设计的原因:
预留空间给对象头:
确保数组本身加上对象头不会超过
Integer.MAX_VALUE
8 字节是保守估计,考虑了不同 JVM 实现可能的对象头大小差异
上述就是ArrayList的扩容源码分析的全部内容啦,不知道您对文章中的问题和思想是否都学会理解了呢?
能看到这里相信您一定对小编的文章有了一定的认可。
有什么问题欢迎各位大佬指出
欢迎各位大佬评论区留言修正~~