【问题标题】:Exceeding byte[] array length (over int upper limit) - java.lang.ArrayIndexOutOfBoundsException超过 byte[] 数组长度(超过 int 上限) - java.lang.ArrayIndexOutOfBoundsException
【发布时间】:2012-02-22 15:15:17
【问题描述】:

我有一个 ByteArrayOutputStream 对象,我收到以下错误:

java.lang.ArrayIndexOutOfBoundsException at 
java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:113)

我正在尝试通过一次写入一个 250mb 的 byte[] 块来加载一个有几个 gig 的文件。

我可以看到字节的大小在增长,一旦它达到长度 2147483647,即 int 的上限,它就会在以下行爆炸:

stream.write(buf); 

stream 是 ByteArrayOutputStream,buf 是我以 250mb 块写入流的内容。

本来打算做的

byte result[] = stream.toByteArray();

最后。我可以尝试其他一些方法来支持大于 int 上限的字节数组大小吗?

【问题讨论】:

  • 提个建议:不要在内存中存储那么大的数组。你真的需要一次记住所有这些演出吗?
  • 你真的需要超过 640K 吗?
  • 注意:考虑过大型数组的提议,但没有进入 Java 7。也许我们会在 Java 8 中看到它?
  • 如果你有一台 64G 内存的机器用于运行科学实验,而你的数据是 30G,那么将所有内容加载到内存中是很有意义的——它几乎总是会导致节省大量时间。

标签: java byte bytearrayoutputstream


【解决方案1】:

Java 中的数组根本不能超出int 的范围。

来自JLS section 15.10

DimExpr 中每个维度表达式的类型必须是可转换(第 5.1.8 节)为整数类型的类型,否则会发生编译时错误。每个表达式都经过一元数字提升 (§)。提升的类型必须是 int,否则会发生编译时错误;这意味着,具体来说,维度表达式的类型不能很长。

JVM spec for arraylength

arrayref 必须是引用类型,并且必须引用一个数组。它从操作数堆栈中弹出。它引用的数组的长度是确定的。 该长度作为 int 被推入操作数堆栈

这基本上强制了数组的最大大小。

目前还不清楚您将在加载数据后如何处理数据,但我会尝试不需要将其全部加载到内存中。

【讨论】:

    【解决方案2】:

    使用多个数组。当您达到限制时使用ByteArrayOutputStream.toByteArray() 并使用ByteArrayOutputStream.reset() 重置。

    【讨论】:

      【解决方案3】:

      使用 ByteArrayOutputStream 写入数 GiB 的数据并不是一个好主意,因为所有内容都必须保存在计算机的内存中。正如您所注意到的,一个字节数组被限制为 2^31 个字节 (2GiB)。

      此外,如果您在其中写入更多数据,用于存储该数据的缓冲区不会增长,因此如果使用的缓冲区已满,则必须创建一个新缓冲区(通常为双倍大小),并且必须从中复制所有数据旧缓冲区进入新缓冲区。

      我的建议是使用RandomAccessFile 并将获得的数据保存到文件中。通过 RandomAccessFile 可以对大于 2GiB 的数据文件进行操作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-09-08
        • 1970-01-01
        • 1970-01-01
        • 2022-01-18
        • 2010-10-15
        • 2019-10-10
        • 2017-06-17
        • 2013-02-15
        相关资源
        最近更新 更多