Java objects are stored in a memory area called the heap. This area increases and decreases in size, but has a limited space defined by several factors, depending on the Java version your application is running on. No matter how you reach that limit, you'll get an
OutOfMemoryErrortype of error. If you increase the maximum memory allocation by setting the jvm parameter
-Xmx and your application keeps hitting the limit and throwing this errors, it is very likely you have a memory leak.
A memory leak happens when your application starts storing more objects in memory than the Garbage Collector can get rid of. An object can be removed from memory by the Garbage Collector when there are no references to it, so that means that your application is keeping references to objects it no longer needs, or that need to be handled in a different way to prevent filling up the heap.
The first thing you need to have in order to properly know what's going on in your application's memory management is a heap dump. There are several ways in which you can accomplish that. The first one is by enabling automatic heap dump when your app reaches an
OutOfMemoryError. You can enable that via command line options, like this, when starting the application:
java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=my/favorite/path MyApp
-XX:+HeapDumpOnOutOfMemoryErrormakes the JVM take a heap dump when the app runs out of memory.
-XX:HeapDumpPath=my/favorite/pathspecifies the location where you want the dump to be saved.
The other way to obtain a heap dump is using the
jmap jdk tool. If your application is running only with the JRE, you will have to install the JDK so you can use
jmap. Usage of the command is as follows:
jmap -dump:format=b,file=heapdump.bin <process_id>
The options below are useful to perform analysis on a production environment, since you can extract the heap dump and copy the file over to your machine and load it into a tool. Another way to extract a heap dump is by attaching a tool to a running java application remotely. That involves using JMX, which in turn requires an open port, but if the application is running locally, in the same machine as your tool, you will see it listed:
Once you are connected to the application, you will be able to load the heap dump. Refer to documentation and tutorials for each tool to learn how to take the heap dump.
After you have the heap dump, it's time to look into the data and determine what's causing the memory leak. The dump file can be analyzed with many tools, commercial, free and open source. I would recommend two tools: jvisualvm, and eclipse memory analyzer. If you have installed the JDK in your environment, you already have jvisualvm (it's in the bin directory). The eclipse memory analyzer (MAT) is an eclipse.org project, and can be downloaded from here.
Jvisualvm will give you a list of the most used objects in the heap dump loaded, this can help identifying the memory leak by inspecting on the objects with more instances in the heap or those that are occupying the most amount of bytes.
If you decide to use MAT, I would highly suggest follow the process described in this blog post, in which the author describes the way the tool organizes the data and gives instructions on how to point down the culprit.