When System.gc() or Runtime.getRuntime().gc() method calls are invoked it causes stop-the-world Full GCs. During stop-the-world full GCs, entire JVM will freeze (i.e. user activities will be performed during the period). Typically these GCs take long duration to complete as well. Thus it may impact your SLAs, and it may result in poor user experiences. In this article, let’s see how to address this problem.

Who invokes System.gc()?

System.gc() calls can be invoked from following sources:

  1. Your own application developers might be explicitly calling System.gc() method.
  2. It could be 3rd party libraries, frameworks, sometimes even application servers that you use could be invoking System.gc() method.
  3. It could be triggered from external tools (like VisualVM) through use of JMX
  4. If your application is using RMI, then RMI invokes System.gc() on a periodic interval.

How to detect whether System.gc() calls invoked?

As you can notice, System.gc() calls can be made from multiple sources and not just from your application source code. You cannot grep code to figure out whether System.gc() calls are invoked or not. Thus it poses a hard challenge: How to detect whether System.gc() calls are invoked in your application stack?

gccauses
Fig: GC Causes reported by the tool GCEasy.io

It’s a best practice to enable your GC log in all production instances. It adds negligible/unnoticeable overhead. Now upload your GC log to the Universal Garbage Collection log analyzer tool GCEasy. This tool has a section called ‘GC Causes.’  If GC activity is triggered because of ‘System.gc()’ calls then it will be reported in this section. See the image, (which is an excerpt from the GCEasy generated report), showing that System.gc() was made 4 times during the lifetime of this application.

Solutions to address explicit System.gc() calls

You can address explicit System.gc() call through one of the proposed solutions.

a. -XX:+DisableExplicitGC

You can forcefully disable the System.gc() calls by passing the JVM argument: ‘-XX:+DisableExplicitGC‘. But before using this option, try to understand the reason why first in place this call was made by your application developer or 3rd party framework. Maybe if it’s not for a valid reason, then pass the ‘-XX:+DisableExplicitGC‘ JVM argument.

b. RMI

If your application is using RMI, then you can control the frequency in which System.gc() calls are made. This frequency can be configured using the following system properties:

-Dsun.rmi.dgc.server.gcInterval=n
-Dsun.rmi.dgc.client.gcInterval=n

The default value for these properties in

  • JDK 1.4.2 and 5.0 is 60000 milliseconds (i.e. 60 seconds)
  • JDK 6 and later release is 3600000 milliseconds (i.e. 60 minutes)

You might want to set these properties to a very high value so that it can minimize the impact.