Friday, December 27, 2013

How do you find a memory leak in Java (using for example JHat)? I have tried to load the heap dump up in JHat to take a basic look. However I do not understand how I am supposed to be able to find the root reference (ref) or whatever it is called. Basically I can tell that there are several hundred meg of hash table entries ([java.util.HashMap$Entry or something like that), but maps are used all over the place... Is there some way to search for large maps, or perhaps finding general roots of large object trees?
[Edit] Ok, I've read the answers so far but lets just say I am a cheap bastard (meaning I am more interested in learning how to use JHat than to pay for JProfiler). Also JHat is always available since it is part of the JDK. Unless of course there is no way with JHat but brute force, but I can't believe that can be the case.
Also, I do not think I will be able to actually modify (adding logging of all map sizes) and run it for long enough for me to notice the leak.
share|improve this question
add comment

10 Answers

up vote48down voteaccepted
I use following approach to finding memory leaks in Java. I've used jProfiler with great success, but I believe that any specialized tool with graphing capabilities (diffs are easier to analyze in graphical form) will work.
  1. Start the application and wait until it get to "stable" state, when all the initialization is complete and the application is idle.
  2. Run the operation suspected of producing a memory leak several times to allow any cache, DB-related initialization to take place.
  3. Run GC and take memory snapshot.
  4. Run the operation again. Depending on the complexity of operation and sizes of data that is processed operation may need to be run several to many times.
  5. Run GC and take memory snapshot.
  6. Run a diff for 2 snapshots and analyze it.
Basically analysis should start from greatest positive diff by, say, object types and find what causes those extra objects to stick in memory.
For web applications that process requests in several threads analysis gets more complicated, but nevertheless general approach still applies.
I did quite a number of projects specifically aimed at reducing memory footprint of the applications and this general approach with some application specific tweaks and trick always worked well.
share|improve this answer
2 
Could you tell me how to run the GC manually –  Eager Learner Jan 4 '10 at 9:42
4 
Most (if not all) Java profilers provide you with an option to invoke GC with a click of a button. Or you can call System.gc() from appropriate place in your code. –  Dima Malenko Jan 4 '10 at 19:13
 
Even if we call System.gc() JVM may choose to neglect the call. AFAIK this is JVM specific. +1 to the answer. –  Aniket Thakur 7 hours ago 
add comment
Questioner here, I got to say getting a tool that does not take 5 minutes to answer any click makes it a lot easier to find potential memory leaks.
Since people are suggesting several tools ( I only tried visual wm since I got that in the JDK and JProbe trial ) I though I should suggest a free / open source tool built on the Eclipse platform, the Memory Analyzer (sometimes referenced as the SAP memory analyzer) available on http://www.eclipse.org/mat/ .
What is really cool about this tool is that it indexed the heap dump when I first opened it which allowed it to show data like retained heap without waiting 5 minutes for each object (pretty much all operations was tons faster than the other tools I tried).
When you open the dump the first screen shows you a pie chart with the biggest objects (counting retained heap) and one can quickly navigate down to the objects that are to big for comfort. It also has a Find likely leak suspects which I reccon can come in handly, but since the navigation was enough for me I did not really get into it.
share|improve this answer

No comments: