-1

我从其他方法获得 ByteArrayInputStream 格式的非常大的文件(> 2.5GB)数据。我必须将此数据以 InputStream 格式传递给另一个方法。我编写了以下代码,它对较小的文件执行得很好,但对于大小超过 2GB 的大文件却失败了。

ByteArrayInputStream bais = null;
bais = method_Returns_FIle_In_ByteArrayInputStream_Format();
InputStream is = bais;
method_Where_To_send_Data_In_InputStream_Format(is);

但是我的代码本身在第二行中断,出现以下错误:

java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3236)
    at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
    at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153)

已经尝试增加 Java 堆空间大小(-Xms 和 -Xmx)。

任何建议表示赞赏。

4

2 回答 2

3

我从其他方法获得 ByteArrayInputStream 格式的非常大的文件(> 2.5GB)数据。

战争以另一种方式失败了。如果你不能改变“另一种方法”,那你就不走运了。在这里您绝对无能为力。根据定义, ByteArrayInputStream完全是内存中的事情,如果 2.5GB 的数据包含该流的全部内容,那么 BAIS 至少需要 2.5GB 的内存。你对此无能为力

解决方法是使用该方法并修复它。它绝对没有业务以 BAIS 形式发送。InputStream 的“要点”就在名称中:用于流式传输该数据。

如果您无法更改它,并且-Xmx8g在 64 位 VM 上无法修复它,那么就没有什么可做的了。

于 2021-08-22T16:51:38.110 回答
1

您不应该尝试加载整个文件然后从内存中读取它。

try (InputStream is = method_Returns_FIle_In_InputStream_Format()) {
    method_Where_To_send_Data_In_InputStream_Format(is);
}

以上使用 try-with-resources 自动关闭is,即使在异常或中断或返回时也是如此。

文件读取方法可以做

Path path = Paths.get("phantasies.log");
return Files.newInputStream(path);

当想要对文件输入进行一些额外处理时,可以InputStreamFilterInputStream.

这也表明针对接口(InputStream)而不是实际实现(ByteArrayInputStream)进行编程更好。

如果ByteArrayInputStream源于收集一个. OutputStream_PipedInputStreamPipedOutputStreamThread

或者,可以使用压缩来减少内存中的大小,a GZipInputStream/ GZipOutputStream

于 2021-08-22T17:10:27.563 回答