Finding Memory Leaks in Java Apps
Here is a small HOWTO on how to find memory leaks with Java SE.
I’ve written it while trying to find memory leaks in our testing tools: JTHarness and ME Framework, and then wanted to share the HOWTO with the world, but I didn’t have my blog at that time, so I posted this info as a comment to a relevant entry in the excellent Adam Bien’s blog.
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:
java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9000 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -agentlib:hprof=heap=dump,file=/tmp/hprof.bin, format=b,depth=10 -jar java_app.jar
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:
jconsole
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:
jps
It will print something like:
15976 java_app.jar
7586 startup.jar
22476 Jps
12248 Main
5437 Bootstrap
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:
http://localhost:7000
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.
April 2nd, 2007 at 2:35 am
[...] The Empty Way Programming, Web and all things Computer. « Finding Memory Leaks in Java Apps [...]
April 3rd, 2007 at 9:04 am
Cool, thanks for the reminder. I saw this long ago and forgot about it completely. Do you know how to do this on a Webapp container?
April 29th, 2007 at 1:03 am
Peace people
We love you
May 9th, 2007 at 4:30 am
Hi all!
You are The Best!!!
G’night
January 7th, 2008 at 8:43 pm
Thanks. Your blog post was very helpful. Really JHAT and JMAP are most intuitive approach to memory leak detection for J2SE apps.
June 11th, 2008 at 7:54 pm
Thanks man!!!
September 22nd, 2008 at 9:40 pm
nice work, brother
September 23rd, 2008 at 6:11 am
Thanks a lot dude, Nice work
September 30th, 2008 at 12:04 pm
Its great dude, Thanks for posting this very good piece of information.
November 5th, 2008 at 1:08 am
Thanks, it really helped me to almost imidielty find the leak i was looking for
.
December 13th, 2008 at 9:01 am
[...] Here’s a good writeup of what to do: http://blog.emptyway.com/2007/04/02/finding-memory-leaks-in-java-apps/ [...]
January 9th, 2009 at 11:14 am
try tijmp
http://www.khelekore.org/jmp/tijmp/
January 24th, 2009 at 12:09 am
If you like jhat, you should be excited by the Eclipse Memory Analyzer(http://www.eclipse.org/mat/) It’s so much better than JHat you won’t believe it.
You can also find some tips at
http://kohlerm.blogspot.com/search/label/memory
January 29th, 2009 at 4:46 am
Thanks a lot…..
February 12th, 2009 at 1:40 am
Good stuff, wakes up the latest techs to probe java memory leaks.
March 10th, 2009 at 10:35 pm
[...] I want to discuss a little bit how I spotted this problem: There are two tools that Java provides, jmap and jhat (really starting with JDK6; unfortunately not supported on the Mac). jmap dumps the entire heap of a JVM into a file. jhat then analyzes that file and provides a HTML interface to browse the results. For more information, look at this article: Finding Memory Leaks in Java Apps. [...]
March 23rd, 2009 at 7:52 pm
hello, i’m trying to find where memory leak is for a web app that is deployed by jboss or knopflerfish, when i run jps i don’t see any pid; how to proceed?
April 3rd, 2009 at 9:39 am
@nanao:
Make sure JBoss is started with the following parameters:
-Dcom.sun.management.jmxremote.port=9998
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
Then: start jconsole en connect to ‘remote process’ with ‘localhost:9998′
Go to the MBeans tab en open:
com.sun.management
HotSpotDiagnostic
Fill in ‘heapdump.bin’ in the ‘String’ inputbox en press ‘dumpHeap’.
Now go the directory where jboss was started (usually the ‘bin’ directory of JBoss) en open heapdump.bin with MAT.
Good luck!
April 3rd, 2009 at 9:41 am
That last part should have been:
Go to the MBeans tab en open:
com.sun.management
HotSpotDiagnostic
Operations
dumpHeap
(so you need to drill down just a bit further until you’ve opened the dumpHeap operation).
Fill in ‘heapdump.bin’ in the ‘String’ inputbox en press ‘dumpHeap’.
Now go the directory where jboss was started (usually the ‘bin’ directory of JBoss) en open heapdump.bin with MAT.
April 11th, 2009 at 4:14 am
[...] http://blog.emptyway.com/2007/04/02/finding-memory-leaks-in-java-apps/ [...]
April 30th, 2009 at 1:07 am
good job
July 10th, 2009 at 8:43 am
How to change the server parameters with Tomcat?
Actually, I am asking about the MBeans part and later…
October 25th, 2009 at 12:24 am
[...] I want to discuss a little bit how I spotted this problem: There are two tools that Java provides, jmap and jhat (really starting with JDK6; unfortunately not supported on the Mac). jmap dumps the entire heap of a JVM into a file. jhat then analyzes that file and provides a HTML interface to browse the results. For more information, look at this article: Finding Memory Leaks in Java Apps. [...]
May 10th, 2010 at 6:04 pm
very nice stuff! love all these tools
July 31st, 2010 at 2:48 pm
[...] program at full speed but only provides names for some classes. This section is in part based on this blog-post, but mine makes the distinctions clearer and provides [...]