Jack Shirazi tells you what garbage collectors and garbage collector combinations are available from the Oracle Java 7 update 4 JVM and onwards, including Java 8 and Java 9.
Published June 2012, Updated September 2015, Author Jack Shirazi
--From http://www.fasterj.com/articles/oraclecollectors1.shtml. Combine Zhou zhiming‘s Understaning JVM with the article to help us practise GC garbage exercises.
Note, this has been updated for changes to Java 8 and Java 9
With G1 finally being officially supported - i.e. no longer an experimental garbage collector - in the 1.7.0_04 (Java 7 update 4) release, it‘s worth taking stock of what we now have available in terms of garbage collectors in the Sun JVM. All the following details are relevant specifically to the Sun JVMs from 1.7.0_04 on.
There are now seven primary garbage collection algorithms, one of which (PS Scavenge) has two modes that are sufficiently different that I would call them two different algorithms (that is, with and without adaptive GC), and another (the concurrent collector) which has a huge number of options that makes it actually at least half a dozen algorithms in one! It‘s useful to list the garbage collectors so that‘s what I‘ll do here.
First I‘ll characterise the actual different primary garbage collectors. There are seven (I‘m counting the G1 collector as one):
Young generation collectors
- Copy (enabled with -XX:+UseSerialGC) -
- the serial copy collector, uses one thread to copy surviving objects from Eden to Survivor spaces and between Survivor spaces until it decides they‘ve been there long enough, at which point it copies them into the old generation.
- PS Scavenge (enabled with -XX:+UseParallelGC) -
- the parallel scavenge collector, like the Copy collector, but uses multiple threads in parallel and has some knowledge of how the old generation is collected (essentially written to work with the serial and PS old gen collectors).
- ParNew (enabled with -XX:+UseParNewGC) -
- the parallel copy collector, like the Copy collector, but uses multiple threads in parallel and has an internal ‘callback‘ that allows an old generation collector to operate on the objects it collects (really written to work with the concurrent collector).
- G1 Young Generation (enabled with -XX:+UseG1GC) -
- the garbage first collector, uses the ‘Garbage First‘ algorithm which splits up the heap into lots of smaller spaces, but these are still separated into Eden and Survivor spaces in the young generation for G1.
Old generation collectors
- MarkSweepCompact (enabled with -XX:+UseSerialGC) -
- the serial mark-sweep collector, the daddy of them all, uses a serial (one thread) full mark-sweep garbage collection algorithm, with optional compaction.
- PS MarkSweep (enabled with -XX:+UseParallelOldGC) -
- the parallel scavenge mark-sweep collector, parallelised version (i.e. uses multiple threads) of the MarkSweepCompact.
- ConcurrentMarkSweep (enabled with -XX:+UseConcMarkSweepGC) -
- the concurrent collector, a garbage collection algorithm that attempts to do most of the garbage collection work in the background without stopping application threads while it works (there are still phases where it has to stop application threads, but these phases are attempted to be kept to a minimum). Note if the concurrent collector fails to keep up with the garbage, it fails over to the serial MarkSweepCompact collector for (just) the next GC.
- G1 Mixed Generation (enabled with -XX:+UseG1GC) -
- the garbage first collector, uses the ‘Garbage First‘ algorithm which splits up the heap into lots of smaller spaces.
All of the garbage collection algorithms except ConcurrentMarkSweep are stop-the-world, i.e. they stop all application threads while they operate - the stop is known as ‘pause‘ time. The ConcurrentMarkSweep tries to do most of it‘s work in the background and minimize the pause time, but it also has a stop-the-world phase and can fail into the MarkSweepCompact which is fully stop-the-world. (The G1 collector has a concurrent phase but is currently mostly stop-the-world).
Combinations of Garbage Collectors
That‘s the set of garbage collectors available, but they operate in two different heap spaces and it‘s the combination that is what we actually end up with for a particular JVM setting, so I‘ll also list the combinations that are possible. It doesn‘t explode into a dozen combinations because not all of these collectors work with each other. G1 is effectively an antisocial collector that doesn‘t like working with anyone else; the serial collectors are the "last man picked" collectors; the ‘PS‘ collectors like to work with each other; and ParNew and Concurrent like to work together. From Java 9 that‘s pretty much it (with the addition of being able to turn off adaptive sizing policy) Before that it wasn‘t quite as simple as that, so here is the list of what I consider are the main options in terms of garbage collection algorithm options. As an aside for those who like a bit of trivia, we have actually lost one garbage collection algorithm over time, the "train" (incremental) garbage collector which was available in various JVMs as -Xincgc and -XX:+UseTrainGC - these flags are no longer useful, the former flag is just silently converted into using ParNew and Concurrent, while the latter flag will cause a startup error in this JVM, and from Java 9 we also lose the incremental algorithm in the concurrent collector.
The full list of possible GC algorithm combinations that can work are:
Command Options* | Resulting Collector Combination |
---|---|
-XX:+UseSerialGC | young Copy and old MarkSweepCompact |
-XX:+UseG1GC | young G1 Young and old G1 Mixed |
-XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy | young PS Scavenge old PS MarkSweep with adaptive sizing |
-XX:+UseParallelGC -XX:+UseParallelOldGC -XX:-UseAdaptiveSizePolicy | young PS Scavenge old PS MarkSweep, no adaptive sizing |
-XX:+UseParNewGC (deprecated in Java 8 and removed in Java 9 - for ParNew see the line below which is NOT deprecated) | young ParNew old MarkSweepCompact |
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC | young ParNew old ConcurrentMarkSweep** |
-XX:+UseConcMarkSweepGC -XX:-UseParNewGC (deprecated in Java 8 and removed in Java 9) | young Copy old ConcurrentMarkSweep** |
*All the combinations listed here will fail to let the JVM start if you add another GC algorithm not listed, with the exception of -XX:+UseParNewGC which is only combinable with -XX:+UseConcMarkSweepGC | |
**there are many many options for use with -XX:+UseConcMarkSweepGC which change the algorithm, e.g.
|
Other options equivalent to one of the above:
Command Options Used On Their Own | Equivalent To Entry In Table Above |
---|---|
-XX:+UseParallelGC | -XX:+UseParallelGC -XX:+UseParallelOldGC |
-XX:+UseParallelOldGC | -XX:+UseParallelGC -XX:+UseParallelOldGC |
-Xincgc (deprecated in Java 8 and removed in Java 9) | -XX:+UseParNewGC -XX:+UseConcMarkSweepGC |
-XX:+UseConcMarkSweepGC | -XX:+UseParNewGC -XX:+UseConcMarkSweepGC |
no option on most Windows | -XX:+UseG1GC from Java 9, or before that -XX:+UseSerialGC (see also this page) |
no option on most Unix | -XX:+UseG1GC from Java 9, or before that -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy (see also this page) |
-XX:+AggressiveHeap | -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy with a bunch of other options related to sizing memory and threads and how they interact with the OS |