The Dreaded OutOfMemoryError

Man screaming at word OutOfMemory

Occasionally during development, your program may crash with an OutOfMemoryError. What happened and how do you prevent it?

What happened?

What happened is that the JVM needed more memory space to run your application than was currently available.

This might happen when you’re developing a relatively large project. It also occasionally happens when you’re using servlet containers or JEE application servers.

When the JVM starts up, it has default sizes for the starting size and the maximum size that the heap can grow to. Remember that the heap is used for all the objects created with the new keyword. The garbage collector manages the heap, and clears objects that are no longer in use. As your program runs and more objects are allocated, the heap grows automatically until it hits the maximum size and then terminates with an OutOfMemoryError.

The default sizes differ substantially from JVM to JVM, and version to version. The starting size might range from a small 8 Mbyte heap to a more substantial 256 MBytes, while the maximum size might range from 256 Mbyte to 4 Gbytes.

What should I do?

The first thing to do if you run into OutOfMemoryErrors is to allocate more heap space to the JVM on startup.

This is easily done using a few optional flags that can be passed to the JVM. These are the –Xms and -Xmx flags of the java JVM.

  • -Xmssize sets the initial heap size (in bytes). This value must be a multiple of 1024 and greater than 1 MB. You can append the letter k or K for kilobytes, m or M for megabytes, and g or G for gigabytes.
    For example, to set the starting size to 64 Mbytes, use -Xms64m. To set it to 2 Gbytes, use -Xms2g.
  • -Xmxsize sets the maximum size of the memory allocation pool (also in bytes). This value must be a multiple of 1024 and greater than 2 MB. Setting the size is the same as for -Xmssize. The default value depends on the system configuration. For server JVMs, -Xms and -Xmx are often set to the same size. The -Xmx option is equivalent to -XX:MaxHeapSize.

Still not solved?

If this doesn’t solve the problem, then you’ll need to look at your program itself.

Your code could be holding onto objects for too long by not deallocating them when you’re done with them. You could unknowingly be causing runaway memory allocation. The code could be poorly optimized. You could have a programming error that causes a memory leak. All of these errors will eventually throw an OutOfMemoryError.

In that case, you will need to look at your code, not at the runtime flag options. Using a profiler is a good first step here. This will be the topic of another tip later…

An easy way to test the results of using the previous runtime flags would be to run the following code from the command line using different values for the –Xms and -Xmx options. Try using the -verbose:gc option to get the garbage collector to print out a message every time it runs.

/**
 * A simple program to print some memory statistics 
 *  before and after invoking the garbage collector.
 *
 * r.totalMemory() is a bit of a misnomer.
 * It returns the current size of the heap.
 */

public class GarbageCollector  {

  public static void main(String args[]) {    

    // getting a reference to the JVM runtime
    Runtime r = Runtime.getRuntime();   

    // setting up a string for formatting
    final String fmt = "%-7s memory size = %,15d bytes%n";    

    // printing out information about the JVM memory
    System.out.printf(fmt, "Maximum", r.maxMemory());
    System.out.printf(fmt, "Current", r.totalMemory());
    System.out.printf(fmt, "Free",    r.freeMemory());    

    // run the garbage collector to free memory
    System.gc();
    System.out.printf(fmt, "Free", r.freeMemory());
    }

  } // end of class

I hope this solved your problem!

If you found this useful, please leave a comment. And sign up to get our weeklyJava tips.

Leave a Comment

Your email address will not be published. Required fields are marked *