Reputation: 2255
Why does my garbage collector(G1 GC) do not release memory altough he could?
The Used Heap is going up over time, the step fall at the end is because I forced the GC to release memory through jcmd <pid> GC.run
Why is that? Is that normal behaviour?
I started the GC with these parameter -Xms64m -Xmx256m -XX:G1ReservePercent=50
Upvotes: 2
Views: 2792
Reputation: 1
This is a common problem and here is the solution: After completion of that object's usage we have to nullify the object.
Upvotes: 0
Reputation: 718788
That graph looks like normal behavior.
G1 GC is a generational collector. That means that the heap is divided into (in this case) 2 generations: new and old. The new generation is collected more frequently than the old one. Objects that survive a number of new generation collections get "promoted" to the old generation. The new generation is relatively small and is GC'd frequently. The old generation is larger, but it is only GC'd when it is starting to get full.
So ... the graph shows a series of "fine" sawtooths that correspond to the new generation collections. The line trends upwards as survivor objects get promoted to the old generation. And the old generation collection is not running ... because the JVM hasn't figured that the old generation is full enough to warrant collection.
Then, you called jcmd <pid> GC.run
. That triggered an old generation collection, and you got back about 10MB of memory. (You didn't need to do that. Freeing up the memory early does nothing except change the graph.)
Then the new collection pattern resumed.
Q: Is this normal?
A: Yes.
Q: Is there a problem here?
A: There is no evidence of a problem. Certainly not with the GC itself. It is possible that your application has a memory leak, but there is no clear evidence one way or the other.
Q: What if you hadn't called jcmd <pid> GC.run
?
A: At some point, the JVM will decide that the old generation is full enough to warrant starting an old generation collection. There is no need to force it. In fact, it is generally a bad idea to force it; see Why is it bad practice to call System.gc()?.
Q: Is this a flaw with GC? Why doesn't the GC release memory when >I< think it is free?
A: No it isn't a flaw. This is by design.
There is a trade-off between the (supposed) benefit of reclaiming memory early versus the cost of running the garbage collector. As a general rule, GC algorithms are most efficient when the ratio of collectable garbage to non-collectable objects is high; i.e. when the heap is getting close (but not too close) to full.
Note that the graphs don't show the reclaimable space. The only way that the JVM can efficiently determine how much space is reclaimable is by actually running the GC to reclaim it. It would be inefficient (and pointless) for the JVM to continually run the GC just so that memory is freed up when >you< think it should be.
Finally, even if you do force the GC to run, the JVM will be reluctant to give memory back to the OS for other processes to use. It is more efficient to hang onto the memory than to be continually downsizing and then re-upsizing the heap.
Upvotes: 4
Reputation: 127
It is totally common and its one of the flaws of Garbagecollection. You can tell the Garbage collector that he should start cleaning your memory but it doesnt mean he will do it.
System.gc();
The official Oracle documentation states that:
Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse
Upvotes: -3