Which GC collector does JDK 8 use by default?

Why JDK8? It’s not 9 or 10, right? Since JDK8 still has the highest market share, I have done in-depth exploration for this version.

Prior to JDK 9, mentioned in Understanding the Java Virtual Machine 3rd edition, page 128, Server was using the Parallel Avenge + Serial Old(PS MarkSweep) by default. Is this true? With this question in mind, I did the following verification

  1. Use the command directly to view the current JVM default parameters
java -XX:+PrintCommandLineFlags -versionCopy the code

Enter the following

-XX:InitialHeapSize=268435456 
-XX:MaxHeapSize=4294967296 
-XX:+PrintCommandLineFlags 
-XX:+UseCompressedClassPointers 
-XX:+UseCompressedOops 
-XX:+UseParallelGC
java version "1.8.0 comes with _162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, mixed mode)Copy the code

The insane are the Parallel insane, and the Serial Old avenge avenge. Use the Parallel Avenge avenge

Parallel Scavenge + Serial OldCopy the code

Here is the type of collector for each parameter

Recycle -xx: -useserialgcserial + Serial old-xx: -useparnewgcparnew + Serial old-xx: -useparallelgcparallel Scavenge + Serial Old-XX:-UseParallelOldGCParallel Scavenge + Parallel Old-XX:-UseConcMarkSweepGCCMS + ParNew-XX:-UseG1GCG1

Track I explore open another trip, this time I use ManagementFactory getGarbageCollectorMXBeans print () the specific collector don’t see is ok? The detailed code is as follows

import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.util.List;
public class GcCollectorPrinter {
    public static void main(String[] args) {
        List<GarbageCollectorMXBean> beans = ManagementFactory.getGarbageCollectorMXBeans();
        for(GarbageCollectorMXBean bean : beans) { System.out.println(bean.getName()); }}}Copy the code

The output of the direct run is as follows

PS Scavenge
PS MarkSweepCopy the code

So PS MarkSweep means Serial Old, right? So what does -xx :+UseParallelOldGC print out? I set the parameters and run the following two commands again

javac GcCollectorPrinter.java 
java -XX:+UseParallelOldGC GcCollectorPrinterCopy the code

Here is the print result

PS Scavenge
PS MarkSweepCopy the code

Wait, am I getting more confused? -xx :+UseParallelOldGC and -xx :+UseParallelGC result in PS MarkSweep. I have two conjectures at this point

  1. PS MarkSweep is just another name for the collector, and it can refer to Serial Old and Parallel Old, since their implementations are basically the same.
  2. -xx :+UseParallelGC -xx :+UseParallelOldGC ParallelOld

-xx :+PrintGCDetails: -xx :+PrintGCDetails: -xx :+PrintGCDetails: -xx :+PrintGCDetails

java -XX:+UseParallelOldGC -XX:+PrintGCDetails GcCollectorPrinter
java -XX:+PrintGCDetails GcCollectorPrinterCopy the code

The results were surprisingly consistent

PS Scavenge PS MarkSweep Heap PSYoungGen total 76288K, used 3932K [0x000000076ab00000, 0x0000000770000000, 0x00000007c0000000) eden space 65536K, 6%, informs [x000000076ab00000 0, 0 x000000076aed7240, 0 x000000076eb00000) from space 10752 k, 0%, informs [x0000000770000000 x000000076f580000 0, 0 x000000076f580000, 0) to space 10752 k, 0%, informs [x000000076eb00000 0, 0 x000000076eb00000, 0 x000000076f580000) ParOldGen total 175104 k, used 0K [0x00000006c0000000, 0x00000006cab00000, 0x000000076ab00000) object space 175104K, 0%, informs [x00000006c0000000 0, 0 x00000006c0000000, 0 x00000006cab00000) Metaspace informs the 2729 k, capacity 4486 k, committed 4864K, reserved 1056768K class space used 297K, capacity 386K, committed 512K, reserved 1048576KCopy the code

ParallelOld -xx :+UseParallelGC -xx :+UseParallelOldGC ParallelOld -xx :+UseParallelOldGC

PS MarkSweep is an alias for Serial Old and Parallel Old. It can be used to verify that the Parallel Old collector is removed by using the following command: Let’s see what happens

java -XX:-UseParallelOldGC -XX:+PrintGCDetails GcCollectorPrinterCopy the code
PS Scavenge PS MarkSweep Heap PSYoungGen total 76288K, used 3932K [0x000000076ab00000, 0x0000000770000000, 0x00000007c0000000) eden space 65536K, 6%, informs [x000000076ab00000 0, 0 x000000076aed7240, 0 x000000076eb00000) from space 10752 k, 0%, informs [x0000000770000000 x000000076f580000 0, 0 x000000076f580000, 0) to space 10752 k, 0%, informs [x000000076eb00000 0, 0 x000000076eb00000, 0 x000000076f580000) PSOldGen total 175104 k, 2 0 k [0 x00000006c0000000, 0x00000006cab00000, 0x000000076ab00000) object space 175104K, 0%, informs [x00000006c0000000 0, 0 x00000006c0000000, 0 x00000006cab00000) Metaspace informs the 2728 k, capacity 4486 k, committed 4864K, reserved 1056768K class space used 297K, capacity 386K, committed 512K, reserved 1048576KCopy the code

The only change is that ParOldGen is changed to PSOldGen. After querying, we can confirm that PSOldGen is Serial Old, so we finally have the answer.

  1. PS MarkSweep is just an alias for the collector, which can refer to Serial Old and Parallel Old.
  2. -xx :+UseParallelGC -xx :+UseParallelOldGC ParallelOld

How can anything in the book be false? Let’s get some information to be on the safe side

A few clues can be found on the JDK 8 website: https://urlify.cn/67NnEz

 Parallel compaction is enabled by default if the option -XX:+UseParallelGC has been specified. The option to turn it off is -XX:-UseParallelOldGC.Copy the code

-xx :+UseParallelGC will start the Parallel collector unless you manually turn it off.

Before JDK 7U4, it was true that Serial was used for UserParallelGC. After this release Parallel has matured and replaced the old collector directly. So both JDK 7 and JDK 8 older agents use Parallel collectors after JDK 7U4, but this detail is not updated in the book. The original https://bugs.openjdk.java.net/browse/JDK-6679764http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/rev/24cae3e4cbaa:

Server-class machine ergonomics was introduced in jdk5. If the machine upon whichthe jvm is running is powerful enough (currently, at least 2 physical cores plus at least 2gb of memory), the server jvm is invoked using the parallel scavenger rather than the serial scavenger. Currently the old gen collector  used is serial mark-sweep-compact. Now that the parallel old gen collector is mature, we should change to using it instead. Issue LinksCopy the code