使用 JDK HttpClient 下载大文件时出现 OutOfMemoryError

问题描述

当我尝试使用 JDK HttpClient 下载一个文件 (> 10GB) 时,我得到了 OutOfMemoryError。这仅在我使用 BodyHandlers.ofInputStream 时发生。如果我使用 BodyHandlers.ofFile,它不会抛出任何错误。我正在使用 JDK 11。有人知道如何解决这个问题吗?我需要 InputStream 来处理。

OutOfMemoryError 被抛出:

HttpResponse<InputStream> httpResponse = httpClient.send(request,HttpResponse.BodyHandlers.ofInputStream());
try (InputStream responseStream = httpResponse.body()) {
    Files.copy(responseStream,outputFile);
}

没有抛出错误

HttpResponse<Path> httpResponse = httpClient.send(request,HttpResponse.BodyHandlers.ofFile(outputFile));

这是堆栈跟踪。

java.io.IOException: closed
    at jdk.internal.net.http.ResponseSubscribers$HttpResponseInputStream.current(ResponseSubscribers.java:342) ~[java.net.http:?]
    at jdk.internal.net.http.ResponseSubscribers$HttpResponseInputStream.read(ResponseSubscribers.java:393) ~[java.net.http:?]
    at java.io.InputStream.transferTo(InputStream.java:704) ~[?:?]
    at java.nio.file.Files.copy(Files.java:3078) ~[?:?]
    at <Masked for privacy>
    at <Masked for privacy>
    at <Masked for privacy>
Caused by: java.lang.OutOfMemoryError: Java heap space
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:937) ~[?:?]
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:491) ~[?:?]
    at javax.crypto.CipherSpi.bufferCrypt(CipherSpi.java:779) ~[?:?]
    at javax.crypto.CipherSpi.engineDoFinal(CipherSpi.java:730) ~[?:?]
    at javax.crypto.Cipher.doFinal(Cipher.java:2497) ~[?:?]
    at sun.security.ssl.SSLCipher$T12GcmReadCipherGenerator$GcmReadCipher.decrypt(SSLCipher.java:1629) ~[?:?]
    at sun.security.ssl.SSLEngineInputRecord.decodeInputRecord(SSLEngineInputRecord.java:240) ~[?:?]
    at sun.security.ssl.SSLEngineInputRecord.decode(SSLEngineInputRecord.java:197) ~[?:?]
    at sun.security.ssl.SSLEngineInputRecord.decode(SSLEngineInputRecord.java:160) ~[?:?]
    at sun.security.ssl.SSLTransport.decode(SSLTransport.java:110) ~[?:?]
    at sun.security.ssl.SSLEngineImpl.decode(SSLEngineImpl.java:681) ~[?:?]
    at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:636) ~[?:?]
    at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:454) ~[?:?]
    at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:433) ~[?:?]
    at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:637) ~[?:?]
    at jdk.internal.net.http.common.SSLFlowDelegate$Reader.unwrapBuffer(SSLFlowDelegate.java:481) ~[java.net.http:?]
    at jdk.internal.net.http.common.SSLFlowDelegate$Reader.processData(SSLFlowDelegate.java:392) ~[java.net.http:?]
    at jdk.internal.net.http.common.SSLFlowDelegate$Reader$ReaderDownstreampusher.run(SSLFlowDelegate.java:264) ~[java.net.http:?]
    at jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run(SequentialScheduler.java:175) ~[java.net.http:?]
    at jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:147) ~[java.net.http:?]
    at jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198) ~[java.net.http:?]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[?:?]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[?:?]
    at java.lang.Thread.run(Thread.java:834) ~[?:?]

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)