What to do about the Garbage Collector when moving from Java 8 to Java 11
Our most common current Java upgrade is from Java 8 to Java 11 (unsurprisingly as these are the two current long term support versions), and a FAQ we have from our teams asks: what should they do about the garbage collector? The question arises because the default collector changed from the parallel collector in Java 8 to the G1 collector in Java 11*.
1. Identify which garbage collector you are currently running with, and all related settings**, BEFORE moving to Java 11
2. Ensure that you have performance targets (at least service latency or GC pause time targets). If you have none, you probably aren’t worried what GC you have, so no need to go further. (If you compare performance across the upgrade and find a significant degradation, then check you haven’t defaulted to Serial GC*.)
3. Try running with G1. If G1 achieves your targets, stay with it. If not, try some basic tuning e.g. -XX:MaxGCPauseMillis but don’t spend too much effort because…
4. If G1 doesn’t achieve your target, fall back to your old setting (presumably CMS*** or Parallel).
*Java 11 and recent Java 8 (from update191+) will take into account container capacity (CPU and memory). If those are small, the JVM may decide that the container looks like a “client machine” and will default to the Serial collector instead of the G1 or parallel collectors. That might be fine (especially for containers restricted to one or two CPUs), but if that is not what you want, then you should explicitly set the GC algorithm instead of letting the default apply.
**GC logging has changed completely, your Java 8 GC logging options (eg -Xloggc, -XX:+PrintGCDateStamps, etc) are no longer valid. The new options are part of the standardized logging framework, and for GC will look something like
***Although CMS was deprecated in Java 8 with the intention to have it removed in Java 11, it was not removed which means it is still supported. It is likely to be removed before the next LTS version.