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 -version
Copy 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 Old
Copy the code

Here is the type of collector for each parameter

parameter collector
-XX:-UseSerialGC Serial + Serial Old
-XX:-UseParNewGC ParNew + Serial Old
-XX:-UseParallelGC Parallel Scavenge + Serial Old
-XX:-UseParallelOldGC Parallel Scavenge + Parallel Old
-XX:-UseConcMarkSweepGC CMS + ParNew
-XX:-UseG1GC G1


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 MarkSweep
Copy 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 GcCollectorPrinter
Copy the code

Here is the print result

PS Scavenge
PS MarkSweep
Copy 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 MarkSweepIt’s just an alias for the collector that he can refer toSerial OldParallel OldAfter all, their implementations are basically the same.
  2. -XX:+UseParallelGC-XX:+UseParallelOldGCThe result is the same. It’s all usedParallel Old

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

java -XX:+UseParallelOldGC -XX:+PrintGCDetails GcCollectorPrinter
java -XX:+PrintGCDetails GcCollectorPrinter
Copy 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 GcCollectorPrinter
Copy 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 MarkSweepIt’s just an alias for the collector that he can refer toSerial OldParallel Old.
  2. -XX:+UseParallelGC-XX:+UseParallelOldGCThe result is the same. It’s all usedParallel Old

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 Parallel collectors are used by default in JDK 7 and JDK 8 since JDK 7U4, but this detail is not updated in the book. https://bugs.openjdk.java.net/browse/JDK-6679764, http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/rev/24cae3e4cbaa,

Server-class machine ergonomics was introduced in jdk5. If the machine upon which the 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

This article is formatted using MDNICE