Does this memory usage pattern indicate that my Java application leaks memory?

Viewed 1285

I have a Java application that waits for the user to hit a key and then runs a task. Once done, it goes back and waits again. I was looking at memory profile for this application with jvisualvm, and it showed an increasing pattern.

Committed memory size is 16MB. Used memory, on application startup, was 2.7 MB, and then it climbed with intermediate drops (garbage collection). Once this sawtooth pattern approached close to 16MB, a major drop occurred and the memory usage fell close to 4 MB. This major drop point has been increasing though. 4MB, 6MB, 8MB. The usage never goes beyond 16 MB but the whole sawtooth pattern is on a climb towards 16 MB.

Do I have a memory leak?

Since this is my first time posting to StackOverflow, do not have enough reputation to post an image.

3 Answers

That kind of sawtooth pattern is commonly observed and is not an indication of memory leak.

Because garbage collecting in big chunks is more efficient than constantly collecting small amounts, the JVM does the collecting in batches. That's why you see this pattern.

Modern SunOracle JVMs use what is called a generational garbage collector:

  1. When the collector runs it first tries a partial collection only releases memory that was allocated recently
  2. recently created objects that are still active get 'promoted'
  3. Once an object has been promoted a few times, it will no longer get cleaned up by partial collections even after it is ready for collection
  4. These objects, called tenured, are only cleaned up when a full collection becomes necessary in order to make enough room for the program to continue running

So basically, bits of your program that stick around long enough to get missed by the fast 'partial' collections will hang around until JVM decides it has to do a full collection. If you let it go long enough you should eventually see the full collection happen and usage drop back down to your original starting point.

If that never happens and you eventually get an Out Of Memory exception, then you probably have a memory leak :)

As stated by others, this behavior is normal. This is a good description of the garbage collection process. To summarize, the JVM usese a generational garbage collector. The vast majority of objects are very short-lived, and those that survive longer tend to last much longer. Knowing this, the GC will check the newer generation first to avoid having to repeatedly check the older objects which are less likely to be inaccessible. After a period of time, the survivors move to the older generation. This increasing saw-tooth is exactly what you're seeing- the rising troughs are due to the older generation growing larger as the survivors are being moved to it. If your program ran long enough eventually checking the newer generation wouldn't free up enough memory and it would have to GC the old generation as well.

Hope that helps.

Related