4

We operate a Java application that we did not develop. This application uses quite a lot of memory for certain tasks, depending on the data, that is manipulated, up to 4GB. At other times, very little memory is needed, around 300MB.

Once the JVM grabs hold of a lot of memory, it takes a very long time until the garbage is collected and even longer until memory is returned back to the operating system. That's a problem for us.

What happens is as follows: The JVM needs a lot of memory for a task and grabs 4GB of Ram to create a 4GB Heap. Then, after processing finished, the memory is filled only 30%-50%. It takes a long time for memory consumption to change. When I trigger a GC (via jConsole) the heap shrinks below 500MB. Another triggered GC and the heap shrinks to 200MB. Sometimes memory is returned to the system, often not.

Here is typical screenshot of VisualVM. The Heap is collected (Used heap goes down) but Heap size stays up. Only when I trigger the GC through the "Perform GC"-Button, Heap size is reduced.

enter image description here

How can we tune the GC to collect memory much earlier? Performance and GC-Pause-Times are not much of an issue for us. We would rather have more and earlier GCs to reduce memory in time. And how can we tweak the JVM to release memory back to the operating system, making the memory used by the JVM smaller?

I do know -XX:MinHeapFreeRatio and -XX:MaxHeapFreeRatio, which helps a bit, but watching the heap with VisualVM shows us, that it's not always obeyed. We set MaxHeapFreeRatio to 40% and see in VisualVM, that the heap is only filled to about 10%.

We can't reduce the maximum memory (-Xmx) since sometimes, for a short period, a lot of memory is acutally needed.

We are not limited to a particular GC. So any GC that solves the problem best can be applied.

We use the Oracle Hotspot JVM 1.8

  • Maybe try [this question].( http://stackoverflow.com/questions/12842863/why-is-garbage-collector-not-doing-a-more-aggressive-garbage-collection-sooner-t) Not sure what you mean by "Give memory back", though. – Christopher Schneider Mar 15 '17 at 19:12
  • "Give memory back" means to release memory back to the operating system, so more memory can be used by other applications and that the memory used by the jvm is lower again. – Malte Finsterwalder Mar 15 '17 at 19:33
  • Gotcha. I made the (incorrect) assumption GC released the memory back to the OS. – Christopher Schneider Mar 15 '17 at 19:36
  • Possible duplicate of [Does GC release back memory to OS?](http://stackoverflow.com/questions/30458195/does-gc-release-back-memory-to-os) – the8472 Mar 15 '17 at 21:13
  • None of the possible duplicates really helps in solving the problem fully. It does help to get earlier GC to reduce the used heap. But the JVM does not seam to release memory back to the OS by itself. It does so when a GC is triggered explicitly externally (via Java VisualVM) or internally (via System.gc()). – Malte Finsterwalder Mar 21 '17 at 11:51

1 Answers1

2

I'm assuming you use the HotSpot JVM.

Then you can use the JVM-Option -XX:InitiatingHeapOccupancyPercent=n (0<=n<=100) to force the JVM to do garbage collection more often. when you set n to 0, constant GC should take place. But I'm not sure whether this is a good idea regarding your applications response time.

SilverNak
  • 3,283
  • 4
  • 28
  • 44
  • Do you know, what happens, when the heap is filled more than the provided Threshold, but the memory is all used and can't be freed? Will that result in recurring collections until the heap can actually be collected? – Malte Finsterwalder Mar 15 '17 at 19:25
  • OP did not state which collector he's using. InitiatingHeapOccupancyPercent is only applicable to concurrent collectors, so this advice may not be useful. – the8472 Mar 15 '17 at 21:24
  • 2
    The JVM Option -XX:InitiatingHeapOccupancyPercent=n does not really cause lower memory consumption. It does cause earlier GC and lower used heap, but the memory is not given back to the OS. Only when a GC is triggered explicitly externally (via Java VisualVM) or internally (via System.gc()), memory is given back to the OS. – Malte Finsterwalder Mar 21 '17 at 11:42