Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to download large files without memory issues in java

When I am trying to download a large file which is of 260MB from server, I get this error: java.lang.OutOfMemoryError: Java heap space. I am sure my heap size is less than 252MB. Is there any way I can download large files without increasing heap size?

How I can download large files without getting this issue? My code is given below:

String path= "C:/temp.zip";   
response.addHeader("Content-Disposition", "attachment; filename=\"test.zip\""); 
byte[] buf = new byte[1024];   
try {   

             File file = new File(path);   
             long length = file.length();   
             BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));   
             ServletOutputStream out = response.getOutputStream();   

             while ((in != null) && ((length = in.read(buf)) != -1)) {   
             out.write(buf, 0, (int) length);   
             }   
             in.close();   
             out.close();
like image 269
Hima Bindu Avatar asked Aug 18 '11 11:08

Hima Bindu


People also ask

Can we clear heap memory in Java?

Once an object is not referenced by any other object, it can be cleared out of the heap, in order for the JVM to reclaim and reuse that space. The execution thread that is responsible to clear the heap space is the Garbage Collector.

Does Java use more memory?

Java is also a very high-level Object-Oriented programming language (OOP) which means that while the application code itself is much easier to maintain, the objects that are instantiated will use that much more memory.


1 Answers

There are 2 places where I can see you could potentially be building up memory usage:

  1. In the buffer reading your input file.
  2. In the buffer writing to your output stream (HTTPOutputStream?)

For #1 I would suggest reading directly from the file via FileInputStream without the BufferedInputStream. Try this first and see if it resolves your issue. ie:

FileInputStream in = new FileInputStream(file);   

instead of:

BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));   

If #1 does not resolve the issue, you could try periodically flushing the output stream after so much data is written (decrease chunk size if necessary):

ie:

try
{
    FileInputStream fileInputStream  = new FileInputStream(file);
    byte[] buf=new byte[8192];
    int bytesread = 0, bytesBuffered = 0;
    while( (bytesread = fileInputStream.read( buf )) > -1 ) {
        out.write( buf, 0, bytesread );
        bytesBuffered += bytesread;
        if (bytesBuffered > 1024 * 1024) { //flush after 1MB
            bytesBuffered = 0;
            out.flush();
        }
    }
}
finally {
    if (out != null) {
        out.flush();
    }
}
like image 149
JJ. Avatar answered Sep 28 '22 06:09

JJ.