首页 > 解决方案 > java.lang.OutOfMemoryError: Java 堆空间 Files.readAllBytes(path)

问题描述

我正在将一个大文件(18 GB)转换为一个字节[],但我收到了这个错误:

java.lang.OutOfMemoryError: Java heap space

这是负责异常的代码:

byte[] content = Files.readAllBytes(path); 

我正在创建字节数组以通过网络发送它:

createFile(filename.toString(),content);

private ADLStoreClient client; // package com.microsoft.azure.datalake.store
public boolean createFile(String filename, byte[] content) {
        try {
            // create file and write some content
            OutputStream stream = client.createFile(filename, IfExists.OVERWRITE);
            // set file permission
            client.setPermission(filename, "777");
            // append to file
            stream.write(content);
            stream.close();

        } catch (ADLException ex) {
            printExceptionDetails(ex);
            return false;
        } catch (Exception ex) {
            log.error(" Exception: {}", ex);
            return false;
        }
        return true;
    }

显然 readAllBytes() 将所有字节读入内存并导致 OutOfMemoryError,我认为这可以使用流来解决,但我不擅长它们,任何人都可以给出适当的解决方案,谢谢

标签: javaspringfile

解决方案


正如 Azure ADLStoreClient 文档所述:

createFile(String path, IfExists mode)

创建一个文件。如果overwriteIfExists为 false 并且文件已经存在,则抛出异常。该调用返回一个ADLFileOutputStream然后可以写入的。

所以是这样的:

try (InputStream in = new FileInputStream(path);
     OutputStream out = client.createFile(filename, IfExists.OVERWRITE)) {
    IOUtils.copyLarge(in, out);
}

您可以自己获取IOUtilscommons-io制作copyLarge例程,这非常简单:

void copyLarge(InputStream in, OutputStream out) throws IOException {
    byte[] buffer = new byte[65536];
    int length;
    while ((length = in.read(buffer)) > 0) {
        out.write(buffer, 0, length);
    }
}

推荐阅读