从零开始学Java-你不知道的数组长度的秘密

前言

今天在做题目的时候,无意中发现ArrayList(JDK 1.8)中定义了一个最大数组长度的常量:

    /**
     * The maximum size of array to allocate.
     * Some VMs reserve some header words in an array.
     * Attempts to allocate larger arrays may result in
     * OutOfMemoryError: Requested array size exceeds VM limit
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

这给我整懵逼了。。。于是有了下面的事情。。

数组对象长度极限

要说这个,必须得从对象的内存结构开始。
下面的大小以32bit操作系统为例

  • 对象头Header
  1. MarkWord - 4Byte
    记录对象运行时数据,例如:hashCode,分代年龄,锁信息等等
  2. 类型指针 - 4Byte
  3. 数组对象长度 - 4Byte
    这个是数组对象独有
  • 实例数据
  • 对其填充

可以看到对于数组对象而言,需要在Header中用4个字节的长度保存数组长度,以此确定数组对象的大小。

所以,理论上,最大的数组长度,应该是Integer.MAX_VALUE。对的,就是理论上!因为不同的虚拟机实现上有差异。有些虚拟机会占用这4个字节的中的bits来存储一些信息。而HotSpot虚拟机所允许的最大数组长度是Integer.MAX_VALUE - 2.

如果有同学想要自己验证一把,可以先用-Xmx3g以上的堆空间大小,然后创建数组 byte[] art = new byte[Integer.MAX_VALUE - 2]
如果出现OOM:java heap space,则证明堆空间还是太小了,加大堆空间。因为Integer. MAX_VALUE=2^32次幂,2g * 1byte =2GB.注意空间大小就行了。如果出现OOM:Requested array size exceed VM limit. 则说明数组长度超过了虚拟机允许的最大长度。

ArrayList中的数组长度极限

本文开篇就给各位贴了代码了。为啥HotSpot最大长度是Integer.MAX_VALUE - 2,但是Java的ArrayList却要定义为Integer.MAX_VALUE - 8?
细心的朋友应该从上面的解释以及源码中的注释找到答案:
Some VMs reserve some header words in an array.
一些虚拟机实现在数组对象中保留一些header位数。这同样也是上面说的同一个意思。从中也可以看到,最多保留3bit。这也是Java源码严谨之处,屏蔽掉底层VM的实现差异。

最后

在JDK13开始,数组长度的极限定义,已不在ArrayList中,而是在ArraysSupport中。
总算搞清楚了,不枉我花费一下午(其实秘密一直都在源码注释中写的明明白白!)。。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值