Sometimes Java processes start accumulating memory over time and do not give them back to the OS. In previous versions of Java, this was a limitation of the JVM. In Java 8 and newer, with the arrival of the G1 garbage collector, the JVM releases memory back to the OS after a GC run.
Now since this is possible, calling a GC, although there is still free memory available becomes a different meaning. On the other hand most application aren’t build with that in mind, so they do not offer any public interface to trigger a GC.
Luckily, the Oracle JDK has a tool for that call “jcmd”.
/usr/lib/java/jdk-1.8.0-66_H02-linux_x64/bin/jcmd {PID} GC.run
Now, to invoke this regularly and not only invoking one, but all engines running this application jar, I used the following script and hooked that into the crontab.
#!/bin/bash
/usr/lib/java/jdk-1.8.0-66_H02-linux_x64/bin/jcmd | grep app.jar | cut --delimiter=' ' -f 1 | while read -r line
do
/usr/lib/java/jdk-1.8.0-66_H02-linux_x64/bin/jcmd $line GC.run
sleep 1;
done
Now, every couple of hours, a GC is invoked on the JVM, so the memory bloat stays within reason.