My simple goal: monitor the memory usage of a Java application so I can be warned when the application is getting dangerously close to throwing an OutOfMemoryError
.
Yes, simple to state, but coming up with a correct solution seems very complicated. Some of the complicating factors are:
OutOfMemoryError
:
permgen
space, which has it's own size limit (set via -XX:MaxPermSize=
)-Xmx
)OutOfMemoryError
.System.gc()
guaranteed that the VM would reclaim all possibly reclaimable object (unreferenced and/or weakly referenced object), but it doesn't. So invoking System.gc()
and then Runtime.freeMemory()
is not reliable.So what is a good and reliable way to answer the question: Is my Java application getting to throwing an OutOfMemoryError
?
Put another way, suppose application version X runs fine and has no memory leak, but version X + 1 has a slow unrecognized memory leak. I'd like to be alerted by this monitoring before version X + 1 throws an OutOfMemoryError
, but I'd like the exact same monitoring to not give false positives for version X. There may be some tuning required in setting up this monitoring - that's OK.
One possible answer might be something like: what is the maximum, over the past N "full" GC runs, of the heap utilization immediately after the GC run? If this value exceeds X% of the total allocated memory, then sound the alarms.
The idea is to determine "application memory usage" in simple number like a percentage, or even something like LOW, MEDIUM, or HIGH, and then monitor this value.
The jstat command gives lots of relevant information, the problem is boiling it down to a simple answer and avoiding false positives (or negatives) caused by the complicating factors listed above.
A small Java application might have a memory leak, but it will not matter if the JVM has enough memory to run your program. However, if your Java application runs constantly, then memory leaks will be a problem. This is because a continuously running program will eventually run out of memory resources.
Using VisualVM (jvisualvm) jvisualvm is a tool to analyse the runtime behavior of your Java application. It allows you to trace a running Java program and see its the memory and CPU consumption. You can also use it to create a memory heap dump to analyze the objects in the heap.
When you run the JVM without the maximum heap size for the server JVM it uses 1/4 of main memory up to 32 GB. If you use the 32-bit windows client VM, it uses 64MB or 128MB. The best way to determine the required memory consumption is to test you application with different memory sizes.
If you watch a memory graph of a long-running application (collected with a tool like jconsole, for example) you'll see a characteristic sawtooth pattern: memory usage climbs, then is GC'd back to a baseline, and then it climbs again. For a healthy app, the peaks and valleys are in two straight horizontal lines. For a leaking app, though, the baseline climbs. That's really what you need to watch for: if each successive GC is less effective than the last, then something is rotten in Denmark.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With