1

Awhile ago I was seeking help on the code below and finally started working on it again. Basically, I've narrowed my error down to the size of the file causing this error:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

The line right below that error in the stack trace is: at java.util.Arrays.copyOf(Arrays.java:2786)

I can pass this program a large directory with thousands of smaller files, but any file over this 50 Mb size tends to crash. I haven't traced the exact size that the program crashes on but I know that at least a 50 Mb file causes issues.

Below are the primary snippets and where the stack trace tells my that my code is breaking.

private void handleFile(File source)
{
    FileInputStream fis = null;

    try
    {
        if(source.isFile())
        {
            fis = new FileInputStream(source);
            handleFile(source.getAbsolutePath(), fis);
        }
        else if(source.isDirectory())
        {
            for(File file:source.listFiles())
            {
               if(file.isFile())
               {
                   fis = new FileInputStream(file);
                   handleFile(file, fis);
               }
               else
               {
                   handleFile(file);
               }
            }
         }
     }
     catch(IOException ioe)
     {
         ioe.printStackTrace();
     }
     finally
     {
         try
         {
             if(fis != null) { fis.close(); }
         }
         catch(IOException ioe) { ioe.printStackTrace(); }
     }
}

private handleFile(String fileName, InputStream inputStream)
{
    byte[] startingBytes = null;

    try
    {
       startingBytes = inputStreamToByteArray(inputStream);

       if(startingBytes.length == 0) return;

       if(isBytesTypeB(startingBytes))
       {
          do stuff
          return;
       }
     }
     catch(IOException ioe)
     {
         ioe.printStackTrace();
     }
}

private byte[] inputStreamToByteArray(InputStream inputStream)
{
    BufferedInputStream bis = null;
    ByteArrayOutputStream baos = null;

    try
    {
        bis = new BufferedInputStream(inputStream);
        baos = new ByteArrayOutputStream(bis);

        byte[] buffer = new byte[1024];

        int nRead;
        while((nRead = bis.read(buffer)) != -1)
        {
            baos.write(buffer, 0, nRead);
        }
    }
    finally { baos.close(); }

    return baos.toByteArray();
 }

 private boolean isBytesTypeB(byte[] fileBytes)
 {
     // Checks if these bytes match a particular type
     if(BytesMatcher.matches(fileBytes, fileBytes.length))
     {
         return true;
     }
     return false;
 }

So there is something in the above code that is causing the error. Any ideas what I'm doing wrong here?

8
  • A workaround would be to increase the heap memory when running your application. Still, if you're just copying a file, why do you have to keep the whole file in RAM? Commented May 8, 2013 at 17:37
  • My program needs the file in RAM because it will eventually do something with the bytes its reading in. Commented May 8, 2013 at 17:38
  • Why don't just process these in chunks? If you specify the real problem you could get a real answer instead of workarounds. Commented May 8, 2013 at 17:39
  • I don't completely understand your comment? The real problem as I understand it is that I'm running out of memory on large files before my program even gets to do anything with the bytes I've read in. Commented May 8, 2013 at 17:41
  • 1
    The question is: why do you need the whole file in RAM? Is it really necessary? Since you're just using the bytes inside it (at least from your example) why don't just use small chunks of byte[] and process them instead of processing the whole byte[] that comes from your file? Commented May 8, 2013 at 17:43

3 Answers 3

2

Arrays.copyOf is invoked each time the ByteArrayOutputStream's internal array needs resizing. This is the moment of the highest memory demand. You can avoid array resizing by specifying the initial size of the array equal to the file size.

Sign up to request clarification or add additional context in comments.

4 Comments

So your suggestion would be to obtain the size of the file and then allocate that size to the size of the byte array?
Yes, that's the only way to avoid the extra memory need. You can also consider Java NIO approaches, such as memory-mapped files, which you can access just like an in-memory array. You will actually be accessing the native memory of the OS's disk cache.
Yes, that's the only way to avoid the extra memory need. You can also consider Java NIO approaches, such as memory-mapped files, which you can access just like an in-memory array. You will actually be accessing the native memory of the OS's disk cache.
I tried to do as you suggested byte specifying the size of the file in the constructor of ByteArrayOutputStream, but I'm still getting the same error. Am I doing this incorrectly? ByteArrayOutputStream baos = new ByteArrayOutputStream((int) fileSize);
1

I haven't read all your code, but it is possible to start Java with more heap space available

java -Xmx128m

for example.

Comments

1

you can increase your heap space from Windows> Preferences> Java> Installed JREs from there select the JRE and click edit, then write in the Default VM Arguments: to -Xmx2048 (it will allocate 2gb)

4 Comments

Is it common for one to need to make this modification? Could it be poor coding that is causing me to have to modify my settings in this way? I tried passing chunks of my data but one of my method requires all of the bytes to operate on the data correctly.
@StinePike.. sorry for got to tag you in my comment above.
I think it is okay if you can figure out what is your maximum limit. But offcourse this will not give you infinite amount of memory. So for some obvious cases if it is needed for your applciation to allocate more memory then you can follow this
And definitely the best way is to optimize your code if possible.. do as the other answer suggested

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.