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.

23 Responses to “Finding Memory Leaks in Java Apps”

  1. The Empty Way » Blog Archive » Finding Memory Leaks, Part 2: Links Says:

    [...] The Empty Way Programming, Web and all things Computer. « Finding Memory Leaks in Java Apps [...]

  2. Toni Says:

    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?

  3. HelloWorld Says:

    Peace people

    We love you

  4. Terabanitoss Says:

    Hi all!
    You are The Best!!!
    G’night

  5. Watsh Rajneesh Says:

    Thanks. Your blog post was very helpful. Really JHAT and JMAP are most intuitive approach to memory leak detection for J2SE apps.

  6. Jim Says:

    Thanks man!!!

  7. Jopsuenuesluct Says:

    nice work, brother

  8. Amith GC Says:

    Thanks a lot dude, Nice work

  9. Jeson Says:

    Its great dude, Thanks for posting this very good piece of information.

  10. Matt Says:

    Thanks, it really helped me to almost imidielty find the leak i was looking for ;) .

  11. Stefan’s Kugel » Blog Archive » Memory Leak in Java Says:

    [...] Here’s a good writeup of what to do: http://blog.emptyway.com/2007/04/02/finding-memory-leaks-in-java-apps/ [...]

  12. subway Says:

    try tijmp

    http://www.khelekore.org/jmp/tijmp/

    ;-)

  13. Markus Kohler Says:

    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

  14. Naveen Bethur Says:

    Thanks a lot…..

  15. Vetrivel R Says:

    Good stuff, wakes up the latest techs to probe java memory leaks.

  16. A Concurrent Affair » Blog Archive » Offline Memory Profiling Says:

    [...] 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. [...]

  17. nanao Says:

    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?

  18. Yuri Says:

    @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!

  19. Yuri Says:

    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.

  20. John’s Blog » Java memory leaks Says:

    [...] http://blog.emptyway.com/2007/04/02/finding-memory-leaks-in-java-apps/ [...]

  21. Shahryar Ghazi Says:

    good job

  22. bozena Says:

    How to change the server parameters with Tomcat?
    Actually, I am asking about the MBeans part and later…

  23. Offline Memory Profiling « SourceForge.net: Project drjava Says:

    [...] 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. [...]

Leave a Reply