As mentioned in the references below, with some commandline arguments to the JVM, you can force periodic Garbage Collection cycles when on low load to reclaim memory that isn't used (because it's not doing anything).
This comes in handy when using containers, where committed unused memory in the node just costs money.
The application is considered inactive, and G1 triggers a periodic garbage collection if the following conditions hold:
- G1PeriodicGCInterval
- number of milliseconds have passed since any previous garbage collection pause and there is no concurrent cycle in progress at this point. A value of zero indicates that periodic garbage collections to promptly reclaim memory are disabled.
- G1PeriodicGCSystemLoadThreshold
- The average one-minute system load value as returned by the getloadavg() call on the JVM host system (e.g. container) is below this value. A value of zero means this is ignored.
As an example:
-XX:G1PeriodicGCInterval=30000 -XX:G1PeriodicGCSystemLoadThreshold=0.5 \
-Xmaxf0.3 -Xminf0.1 -Xmx2048M -Xms32M \
-jar ../releases/mrbear.war
This example would indicate that every 30 seconds, if the average system load is below 0.5, a Garbage Collection cycle may be initiated to reclaim memory.
Java Agent
In the past Virtuozzo, which I used, had to put in a java-agent in the command line to have the same functionality. So this is no longer necessary.
Progress!
References
- Virtuozzo - Elastic JVM with Automatic Vertical Memory Scaling
- https://www.virtuozzo.com/company/blog/elastic-jvm-vertical-scaling/
- JEP 346: Promptly Return Unused Committed Memory from G1
- https://openjdk.org/jeps/346