ArrayList通过MAX_ARRAY_SIZE(Integer.MAX_VALUE-8)硬约束和grow()中两级检查(超限跳转hugeCapacity,再按minCapacity与MAX_ARRAY_SIZE比较返回Integer.MAX_VALUE或MAX_ARRAY_SIZE)实现溢出防护,确保错误明确可捕获。

超大容量时的溢出防护机制
ArrayList 并非无限制扩容,它在底层设有多重防线防止因容量计算失控导致 OutOfMemoryError 或 JVM 堆崩溃。关键不是“能不能扩到极大值”,而是“如何安全地拒绝危险请求”。
容量上限硬约束:MAX_ARRAY_SIZE
JDK 严格定义了数组可分配的最大长度:private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
这个 -8 是预留空间,用于 JVM 内部对象头等元数据,避免某些虚拟机在分配接近 Integer.MAX_VALUE 的数组时因内存对齐失败而抛出异常。
grow() 中的两级兜底判断
当计算出的新容量超出安全范围时,grow(int minCapacity) 会按顺序执行两个关键检查:
- 若
newCapacity - MAX_ARRAY_SIZE > 0(即预估容量已超限),立即跳转至hugeCapacity(minCapacity) -
hugeCapacity()进一步判断:
– 若minCapacity (整数溢出为负),直接抛 <code>OutOfMemoryError;
– 若minCapacity > MAX_ARRAY_SIZE,返回Integer.MAX_VALUE;
– 否则返回MAX_ARRAY_SIZE
实际扩容仍可能失败,但不会静默溢出
即使最终确定新容量为 Integer.MAX_VALUE,Arrays.copyOf() 在真正分配内存时仍可能因堆空间不足而抛出 OutOfMemoryError。但此时错误是明确、可捕获的,而非因整数溢出导致逻辑错乱或静默数据截断。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
例如:向空 ArrayList 一次性 addAll 超过 21 亿个元素,会在 hugeCapacity 阶段就被拦截并抛出带提示的 OOM,而不是尝试分配一个非法大小的数组。
立即学习“Java免费学习笔记(深入)”;

















