Solve java.lang.OutOfMemoryError: Java heap space

If you get an OutOfMemoryError with the message "Java heap space" (not to be confused with message "PermGen space"), it simply means the JVM ran out of memory. When it occurs, you basically have 2 choices:

1. Allow the JVM to use more memory using the -Xmx VM argument. For instance, to allow the JVM to use 1 GB (1024 MB) of memory:
java -Xmx1024m ...
2. Improve/Fix the application so that it uses less memory

In many cases, like in the case of a memory leak, the second option is the only sound choice. A memory leak happens when the application keeps more and more references to objects and never releases them. The garbage collector cannot collect those objects and the application will eventually run out of memory. At this point, the JVM will throw an OOM.

A memory leak can be very latent. For instance, the application might behave flawlessly during development and QA. However, it suddenly throws a OOM after several days in production at customer site. To solve that issue, you first need to find the root cause of it. The root cause can be very hard to find in development if it cannot be reproduced. Follow those steps to find the root cause of the OOM:

1. Start the application with the VM argument -XX:+HeapDumpOnOutOfMemoryError. This will tell the VM to produce a heap dump when a OOM occurs:
java -XX:+HeapDumpOnOutOfMemoryError ...
2. Reproduce the problem. Well, if you cannot reproduce in dev, you will have to use the production environment.
3. Use VisualVM to read the heap dump file and diagnose the issue.

The heap dump file has all information about the memory usage of the application. It allows you to navigate the heap and see what objects use memory and what references prevent the garbage collector from reclaiming the memory. This will give you very strong hints and you will (hopefully) be able to find the root cause of the problem. The problem could be a cache that grows indefinitely, a list that keeps collecting business-specific data in memory, a huge request that tries to load almost all data from database in memory, etc.

Once you know the root cause of the problem, you can elaborate solutions to fix it. In case of a cache that grows indefinitely, a good solution could be to set a reasonable limit to that cache. In case of a query that tries to load almost all data from database in memory, you may have to change the way you manipulate data; you could even have to change the behavior of some functionalities of the application.

If you do not want to wait for an OOM or if you just want to see what is in memory now, you can still generate heap dump. To manually trigger a heap dump, you have 2 choices:

1. Use VisualVM, right-click on the process on the left pane and select Heap Dump

2. If you do not have a graphical environment and can't use vnc (VisualVM needs a graphical environment), use jps and jmap to generate the heap dump file. Then copy the file to your workstation and use VisualVM to read the heap dump (File -> Load...):

user@host:~$ jps
20198
21734 WordFinder
21921 Jps
21168 Main

user@host:~$ jmap -dump:live,format=b,file=heap.bin 21734
Dumping heap to /home/user/heap.bin ...
Heap dump file created

You can also contact my application development company and I can personally help you with those kind of issues.

Here is a screenshot of VisualVM with a heap dump loaded:

Heap Dump in VisualVM 

Alternatively, you can also use jhat to read heap dump files.



Comments:

Post a Comment:
Comments are closed for this entry.