Occasionally during development, your program may crash with an OutOfMemoryError
. What happened and how do you prevent it?
What caused the OutOfMemoryError?
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 do I fix the OutOfMemoryError?
The first thing to do if you run into OutOfMemoryError
s 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 letterk
orK
for kilobytes,m
orM
for megabytes, andg
orG
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. Your feedback helps me write tips that help you.