Finding Memory Leaks in Java Apps
Here is a small HOWTO on how to find memory leaks with Java SE.
Note: Use the latest JDK 6, because it has the latest tools, with lots of bug fixes and improvements. All the later examples assume that JDK6's bin directory is in the PATH.
Step 1. Start the application.
Start the application as you usually do:
java -jar java_app.jar
Alternatively, you could start java with hprof agent. Java will run slower, but the huge benefit of this approach is that the stack traces for created objects will be available which improves memory leak analysis greatly:
When the application is up, perform various actions that you think might lead to memory leaks.
For example, if you open some documents in your app, the memory
graph could rapidly go up. If closing the docs and invocation of full
garbage collection did not bring the memory back to normal level, there
is probably a leak somewhere.You might use
jconsole from JDK 6 to see the memory consumption graph to have a clue whether memory leak is present or not:
It will pop up a dialog with a list of Java applications to connect to. Find the one with java_app.jar and connect. Also, jconsole allows to invoke full GC providing nice button just for that.
Step 2. Find the application pid.
Find out the application?s process id via:
It will print something like:
In our case the pid is 15976.
Step 3. Dump the heap into file.
Dump heap into the file:
jmap -dump:format=b,file=/tmp/java_app-heap.bin 15976
We just told jmap to dump the heap into /tmp/java_app-heap.bin file, in binary from (which is optimized to work with large heaps). The third parameter is the pid we found in Step 2.
Alternatively, if you started java with hprof agent, you could just use Ctrl-\ on Solaris/Linux or Ctrl-Break on Windows to dump heap into the file, specified in hprof agent arguments.
Step 4. Visualize the heap.
Use jhat tool to visualize the heap:
jhat -J-Xmx326m /tmp/java_app-heap.bin
Jhat will parse the heap dump and start a web server at port 7000. Connect to Jhat server by pointing your browser to:
And start investigating.
Jhat allows you to see what objects are present in the heap, who has references to those objects, etc.
Here are some tips:
- Investigate _instances_, not _classes_.
- Use the following URL to see the instances: http://localhost:7000/showInstanceCounts/
- Use ?Reference Chains from Rootset? (Exclude weak refs!!!) to see who?s holding the instance.