java.lang.OutOfMemoryError:从URL下载大文件时的Java堆空间

我想从URL下载文件。 文件大小为564.31MB。 我不知道这里发生了什么错误。 此外,我想知道我的代码是否是从URL下载文件的正确方法。 如果有更好的方法,请详细告诉我为什么它比这更好。 谢谢。

import org.apache.commons.io.FilenameUtils; import java.io.*; import java.net.MalformedURLException; import java.net.URL; /** * Created by lukas on 6/30/16. */ public class Main { public static void main(String[] args){ try { String link = "https://s.basketbuild.com/uploads/devs/dianlujitao/oneplus3/cm13/cm-13.0-20160621-UNOFFICIAL-oneplus3.zip"; URL url = new URL(link); InputStream inputStream = new BufferedInputStream(url.openStream()); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); int n=0; byte[] buf = new byte[1024]; long duration = System.currentTimeMillis(); while((n=inputStream.read(buf))!=-1){ byteArrayOutputStream.write(buf, 0, n); } duration = System.currentTimeMillis()-duration; System.out.println("Finish in "+duration+"ms"); inputStream.close(); File dir = new File("Output path"); if(!dir.exists()) dir.mkdirs(); String fileBaseName = FilenameUtils.getBaseName(link); String fileExtension = FilenameUtils.getExtension(link); System.out.println("Name: "+fileBaseName+'.'+fileExtension); File outputFile = new File(dir, fileBaseName+'.'+fileExtension); if(!outputFile.exists()){ outputFile.createNewFile(); } FileOutputStream fileOutputStream = new FileOutputStream(outputFile); fileOutputStream.write(byteArrayOutputStream.toByteArray()); //release outputstream byteArrayOutputStream.close(); fileOutputStream.close(); System.out.println("Your download has been finished"); } catch (MalformedURLException e) { e.printStackTrace(); System.out.println("Something unexpected has happened!"); } catch (IOException e) { e.printStackTrace(); System.out.println("Something unexpected has happened!"); } } } 

这是我的控制台说的:

 Finish in 133506ms Name: cm-13.0-20160621-UNOFFICIAL-oneplus3.zip Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:3236) at java.io.ByteArrayOutputStream.toByteArray(ByteArrayOutputStream.java:191) at Main.main(Main.java:42) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) 

  1. ByteArrayOutputStream在堆内存中分配其所有数据。 正确的方法是直接写入文件,并使用缓冲区,以便优化磁盘I / O:

      OutputStream os = new BufferedOutputStream(new FileOutputStream(“myFile.txt”)); 
  2. System.currentTimeMillis()为您提供当前日期和时间,可能随时更改。 这并不意味着计算持续时间,使用SystemClock.nanoTime()。