不朽
不朽
发布于 2024-03-14 / 7 阅读
0
0

jdk默认的垃圾回收器

jdk默认的垃圾回收器

查询默认垃圾收集器

通过 Java 命令

使用 -XX:+PrintCommandLineFlags 可以查询 Java 启动时定义好的变量,用它可以看到使用的 GC。

bash复制代码PS C:\Program Files\Java> java -XX:+PrintCommandLineFlags -version
-XX:ConcGCThreads=3 -XX:G1ConcRefinementThreads=13 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=257798976 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=4124783616 -XX:MinHeapSize=6815736 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC -XX:-UseLargePagesIndividualAllocation
java version "16.0.2" 2021-07-20
Java(TM) SE Runtime Environment (build 16.0.2+7-67)
Java HotSpot(TM) 64-Bit Server VM (build 16.0.2+7-67, mixed mode, sharing)

通过代码

代码获取的是实际的垃圾收集器,只要在运行时不添加任何 JVM GC 参数,就会使用默认的 GC。使用代码:

java复制代码import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;

public class CheckDefaultGC {
    public static void main(String[] args) {
        System.out.println("Get JDK Default GC for jdk"
                + System.getProperty("java.version") + " - "
                + System.getProperty("java.vm.name") + ":");
        for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) {
            System.out.println(gcBean.getName());
        }
    }
}

由于 Java 向下兼容的特性,旧版本的 Java 程序可以在新版 JDK 中运行,因此使用 JDK5 编译器将程序编译为 class 文件再编译成 jar 包,供所有 JDK 运行。

不要相信 IDE 运行的结果,有些 IDE 会默认添加 JVM 参数,虽然我们可以修改或者去掉,但也是麻烦事。使用 java 命令最简单。

  • MANIFEST.MF

    MANIFEST.MF复制代码Manifest-Version: 1.0
    Created-By: 1.5.0_22 (Sun Microsystems Inc.)
    Main-Class: com.test.CheckDefaultGC
    
  • 打包

    bash复制代码PS C:\Workspace\Idea\java-test\src> & 'C:\Program Files\Java\jdk1.5.0_22\bin\javac.exe' .\com\test\CheckDefaultGC.java -version
    javac 1.5.0_22
     
    PS C:\Workspace\Idea\java-test\src> & 'C:\Program Files\Java\jdk1.5.0_22\bin\jar.exe' -cfmv check-default-gc.jar .\com\test\CheckDefaultGCManifest.MF .\com\test\CheckDefaultGC.class
    标明清单(manifest)
    增加:com/test/CheckDefaultGC.class(读入= 1138) (写出= 655)(压缩了 42%)
    
  • 测试

    bash复制代码PS C:\Program Files\Java> java -jar C:\Workspace\Idea\java-test\src\check-default-gc.jar
    Get JDK Default GC for jdk16.0.2 - Java HotSpot(TM) 64-Bit Server VM:
    G1 Young Generation
    G1 Old Generation
    

查询默认垃圾收集器

JDK5

JDK5 是 Java 的重大里程碑版本,此前所有 JDK 都称为 JDK 1.x,自第五版本起,改为 JDKX 方式命名。

bash复制代码PS C:\Program Files\Java> .\jdk1.5.0_22\bin\java.exe -jar C:\Workspace\Idea\java-test\src\check-default-gc.jar
Get JDK Default GC for jdk1.5.0_22 - Java HotSpot(TM) 64-Bit Server VM:
PS Scavenge
PS MarkSweep
bash复制代码PS C:\Program Files\Java> .\jdk1.5.0_22\bin\java.exe -XX:+PrintCommandLineFlags -version
-XX:MaxHeapSize=1073741824 
-XX:+UseParallelGC
-XX:+PrintCommandLineFlags 
java version "1.5.0_22"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_22-b03)
Java HotSpot(TM) 64-Bit Server VM (build 1.5.0_22-b03, mixed mode)
  • MaxHeapSize:最大堆大小,即 Xmx,1073741824 = 1G,可以直接指定以 g/m/k 为单位。
  • +UseParallelGC:使用 Parallel 垃圾收集器,即 PS Scavenge 和 PS MarkSweep。

注意这里的 + 号,有 +/- 号表示启用/关闭,没有的表示是配置属性。

JDK6

bash复制代码PS C:\Program Files\Java> .\jdk1.6.0_45\bin\java.exe -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=257798976 
-XX:MaxHeapSize=4124783616 
-XX:ParallelGCThreads=13 
-XX:+UseCompressedOops 
-XX:-UseLargePagesIndividualAllocation 
-XX:+UseParallelGC
-XX:+PrintCommandLineFlags 
java version "1.6.0_45"
Java(TM) SE Runtime Environment (build 1.6.0_45-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01, mixed mode)
  • InitialHeapSize:初始堆大小,即 Xms,257798976 = 245.8M,可以直接指定以 g/m/k 为单位。

  • ParallelGCThreads:并行 GC 线程数量,只要是多线程 GC 就可以设置。

    默认情况下,当 CPU 数量小于8, ParallelGCThreads 的值等于 CPU 数量,当 CPU 数量大于 8 时,根据公式计算得出:ParallelGCThreads = 8+((N-8)×5/8) = 5×N/8+3,这里的 CPU 和 N 指逻辑 CPU 的数量,测试电脑为 16 核心数,因此计算结果为 13 符合。

  • +UseCompressedOops :启用压缩普通对象指针,减少指针内存使用量。

    关于压缩指针个人觉得有一篇文章写的挺好的:JVM之压缩指针(CompressedOops) (juejin.cn)

  • -UseLargePagesIndividualAllocation :关闭???

bash复制代码PS C:\Program Files\Java> .\jdk1.6.0_45\bin\java.exe -jar C:\Workspace\Idea\java-test\src\check-default-gc.jar
Get JDK Default GC for jdk1.6.0_45 - Java HotSpot(TM) 64-Bit Server VM:
PS Scavenge
PS MarkSweep

JDK7

bash复制代码PS C:\Program Files\Java> .\jdk1.7.0_80\bin\java.exe -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=257798976 
-XX:MaxHeapSize=4124783616 
-XX:+UseCompressedOops
-XX:-UseLargePagesIndividualAllocation 
-XX:+UseParallelGC
-XX:+PrintCommandLineFlags 
java version "1.7.0_80"
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)
bash复制代码PS C:\Program Files\Java> .\jdk1.7.0_80\bin\java.exe -jar C:\Workspace\Idea\java-test\src\check-default-gc.jar
Get JDK Default GC for jdk1.7.0_80 - Java HotSpot(TM) 64-Bit Server VM:
PS Scavenge
PS MarkSweep

JDK8

bash复制代码PS C:\Program Files\Java> .\jdk1.8.0_211\bin\java.exe -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=257798976 
-XX:MaxHeapSize=4124783616
-XX:+UseCompressedClassPointers 
-XX:+UseCompressedOops 
-XX:-UseLargePagesIndividualAllocation 
-XX:+UseParallelGC
-XX:+PrintCommandLineFlags
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
  • +UseCompressedClassPointers:启用压缩类型指针。

    每个对象的对象头中都有一个指向所属类型的指针,在 64 位操作系统上默认是 8 个字节的,但开启压缩类型指针之后,可以压缩成 4 个字节,原理和 UseCompressedOops 一样。同时,开启压缩类型指针,必须先开启压缩对象指针。

bash复制代码PS C:\Program Files\Java> .\jdk1.8.0_211\bin\java.exe -jar C:\Workspace\Idea\java-test\src\check-default-gc.jar
Get JDK Default GC for jdk1.8.0_211 - Java HotSpot(TM) 64-Bit Server VM:
PS Scavenge
PS MarkSweep

JDK9

bash复制代码PS C:\Program Files\Java> .\jdk-9.0.4\bin\java.exe -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=257798976 
-XX:MaxHeapSize=4124783616 
-XX:ReservedCodeCacheSize=251658240 
-XX:+SegmentedCodeCache 
-XX:+UseCompressedClassPointers 
-XX:+UseCompressedOops 
-XX:+UseG1GC
-XX:G1ConcRefinementThreads=13 
-XX:-UseLargePagesIndividualAllocation
-XX:+PrintCommandLineFlags 
java version "9.0.4"
Java(TM) SE Runtime Environment (build 9.0.4+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, mixed mode)
  • ReservedCodeCacheSize:设置代码缓存最大值,251658240 = 240M。

    代码缓存是一块独立的内存空间,常被人所忽视,用来存储 JIT 编译的本地代码,一旦代码缓存满了,就会停止 JIT 编译,此时 JVM 完全进入解释型执行。除了之前存储在代码缓存中的代码之外,其他代码不会再执行 JIT 优化,相当于解释型语言。速度会下降一个量级,因此代码缓存大小非常重要。

    同时,Java 所使用的本地方法代码(JNI)也会存在代码缓存中。如果该缓存区满了,也会影响本地方法的执行效率。

    与之对应的是 InitialCodeCacheSize 为起始代码缓存区大小。

  • +SegmentedCodeCache:开启代码缓存分段初始化。

    代码缓存区分为三块:NonNMethodCodeProfiledCodeNonProfiledCode。如果未开启代码缓存分段初始化,这三个区域就会初始化成一个整体,如果开启了,就会初始化成分开的三个区域。

  • +UseG1GC:启用 GC 垃圾收集器。

  • G1ConcRefinementThreads:G1 缓冲区线程数。

bash复制代码PS C:\Program Files\Java> .\jdk-9.0.4\bin\java.exe -jar C:\Workspace\Idea\java-test\src\check-default-gc.jar
Get JDK Default GC for jdk9.0.4 - Java HotSpot(TM) 64-Bit Server VM:
G1 Young Generation
G1 Old Generation

JDK10

bash复制代码PS C:\Program Files\Java> .\jdk-10.0.2\bin\java.exe -XX:+PrintCommandLineFlags -version
-XX:G1ConcRefinementThreads=13 
-XX:InitialHeapSize=257798976 
-XX:MaxHeapSize=4124783616 
-XX:ReservedCodeCacheSize=251658240 
-XX:+SegmentedCodeCache 
-XX:+UseCompressedClassPointers 
-XX:+UseCompressedOops 
-XX:+UseG1GC 
-XX:-UseLargePagesIndividualAllocation
-XX:+PrintCommandLineFlags 
java version "10.0.2" 2018-07-17
Java(TM) SE Runtime Environment 18.3 (build 10.0.2+13)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.2+13, mixed mode)
bash复制代码PS C:\Program Files\Java> .\jdk-10.0.2\bin\java.exe -jar C:\Workspace\Idea\java-test\src\check-default-gc.jar
Get JDK Default GC for jdk10.0.2 - Java HotSpot(TM) 64-Bit Server VM:
G1 Young Generation
G1 Old Generation

JDK11

bash复制代码PS C:\Program Files\Java> .\jdk-11.0.11\bin\java.exe -XX:+PrintCommandLineFlags -version
-XX:G1ConcRefinementThreads=13 
-XX:GCDrainStackTargetSize=64 
-XX:InitialHeapSize=257798976 
-XX:MaxHeapSize=4124783616 
-XX:ReservedCodeCacheSize=251658240 
-XX:+SegmentedCodeCache 
-XX:+UseCompressedClassPointers 
-XX:+UseCompressedOops 
-XX:+UseG1GC 
-XX:-UseLargePagesIndividualAllocation
-XX:+PrintCommandLineFlags 
java version "11.0.11" 2021-04-20 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.11+9-LTS-194)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.11+9-LTS-194, mixed mode)
  • GCDrainStackTargetSize:并发标记子阶段处理时为了保证处理的性能,一次标记的最多对象个数,默认 64。
bash复制代码PS C:\Program Files\Java> .\jdk-11.0.11\bin\java.exe -jar C:\Workspace\Idea\java-test\src\check-default-gc.jar
Get JDK Default GC for jdk11.0.11 - Java HotSpot(TM) 64-Bit Server VM:
G1 Young Generation
G1 Old Generation

JDK12

bash复制代码PS C:\Program Files\Java> .\jdk-12.0.2\bin\java.exe -XX:+PrintCommandLineFlags -version
-XX:G1ConcRefinementThreads=13 
-XX:GCDrainStackTargetSize=64 
-XX:InitialHeapSize=257798976 
-XX:MaxHeapSize=4124783616 
-XX:ReservedCodeCacheSize=251658240 
-XX:+SegmentedCodeCache 
-XX:+UseCompressedClassPointers 
-XX:+UseCompressedOops 
-XX:+UseG1GC 
-XX:-UseLargePagesIndividualAllocation
-XX:+PrintCommandLineFlags 
java version "12.0.2" 2019-07-16
Java(TM) SE Runtime Environment (build 12.0.2+10)
Java HotSpot(TM) 64-Bit Server VM (build 12.0.2+10, mixed mode, sharing)
bash复制代码PS C:\Program Files\Java> .\jdk-12.0.2\bin\java.exe -jar C:\Workspace\Idea\java-test\src\check-default-gc.jar
Get JDK Default GC for jdk12.0.2 - Java HotSpot(TM) 64-Bit Server VM:
G1 Young Generation
G1 Old Generation

JDK13

bash复制代码PS C:\Program Files\Java> .\jdk-13.0.2\bin\java.exe -XX:+PrintCommandLineFlags -version
-XX:G1ConcRefinementThreads=13 
-XX:GCDrainStackTargetSize=64 
-XX:InitialHeapSize=257798976 
-XX:MaxHeapSize=4124783616 
-XX:MinHeapSize=6815736 
-XX:ReservedCodeCacheSize=251658240 
-XX:+SegmentedCodeCache 
-XX:+UseCompressedClassPointers 
-XX:+UseCompressedOops 
-XX:+UseG1GC 
-XX:-UseLargePagesIndividualAllocation
-XX:+PrintCommandLineFlags 
java version "13.0.2" 2020-01-14
Java(TM) SE Runtime Environment (build 13.0.2+8)
Java HotSpot(TM) 64-Bit Server VM (build 13.0.2+8, mixed mode, sharing)
  • MinHeapSize:堆区占用的最小内存,6815736 = 6.5M
bash复制代码PS C:\Program Files\Java> .\jdk-13.0.2\bin\java.exe -jar C:\Workspace\Idea\java-test\src\check-default-gc.jar
Get JDK Default GC for jdk13.0.2 - Java HotSpot(TM) 64-Bit Server VM:
G1 Young Generation
G1 Old Generation

JDK14

bash复制代码PS C:\Program Files\Java> .\jdk-14.0.2\bin\java.exe -XX:+PrintCommandLineFlags -version
-XX:G1ConcRefinementThreads=13 
-XX:GCDrainStackTargetSize=64 
-XX:InitialHeapSize=257798976
-XX:MaxHeapSize=4124783616 
-XX:MinHeapSize=6815736 
-XX:ReservedCodeCacheSize=251658240 
-XX:+SegmentedCodeCache 
-XX:+UseCompressedClassPointers 
-XX:+UseCompressedOops 
-XX:+UseG1GC 
-XX:-UseLargePagesIndividualAllocation
-XX:+PrintCommandLineFlags 
java version "14.0.2" 2020-07-14
Java(TM) SE Runtime Environment (build 14.0.2+12-46)
Java HotSpot(TM) 64-Bit Server VM (build 14.0.2+12-46, mixed mode, sharing)
bash复制代码PS C:\Program Files\Java> .\jdk-14.0.2\bin\java.exe -jar C:\Workspace\Idea\java-test\src\check-default-gc.jar
Get JDK Default GC for jdk14.0.2 - Java HotSpot(TM) 64-Bit Server VM:
G1 Young Generation
G1 Old Generation

JDK15

bash复制代码PS C:\Program Files\Java> .\jdk-15.0.2\bin\java.exe -XX:+PrintCommandLineFlags -version
-XX:ConcGCThreads=3 
-XX:G1ConcRefinementThreads=13 
-XX:GCDrainStackTargetSize=64 
-XX:InitialHeapSize=257798976 
-XX:MarkStackSize=4194304 
-XX:MaxHeapSize=4124783616 
-XX:MinHeapSize=6815736 
-XX:+PrintCommandLineFlags 
-XX:ReservedCodeCacheSize=251658240 
-XX:+SegmentedCodeCache 
-XX:+UseCompressedClassPointers 
-XX:+UseCompressedOops 
-XX:+UseG1GC 
-XX:-UseLargePagesIndividualAllocation
java version "15.0.2" 2021-01-19
Java(TM) SE Runtime Environment (build 15.0.2+7-27)
Java HotSpot(TM) 64-Bit Server VM (build 15.0.2+7-27, mixed mode, sharing)
bash复制代码PS C:\Program Files\Java> .\jdk-15.0.2\bin\java.exe -jar C:\Workspace\Idea\java-test\src\check-default-gc.jar
Get JDK Default GC for jdk15.0.2 - Java HotSpot(TM) 64-Bit Server VM:
G1 Young Generation
G1 Old Generation

JDK16

bash复制代码PS C:\Program Files\Java> .\jdk-16.0.2\bin\java.exe -XX:+PrintCommandLineFlags -version
-XX:ConcGCThreads=3 
-XX:G1ConcRefinementThreads=13 
-XX:GCDrainStackTargetSize=64 
-XX:InitialHeapSize=257798976 
-XX:MarkStackSize=4194304 
-XX:MaxHeapSize=4124783616 
-XX:MinHeapSize=6815736 
-XX:+PrintCommandLineFlags 
-XX:ReservedCodeCacheSize=251658240 
-XX:+SegmentedCodeCache 
-XX:+UseCompressedClassPointers 
-XX:+UseCompressedOops 
-XX:+UseG1GC 
-XX:-UseLargePagesIndividualAllocation
java version "16.0.2" 2021-07-20
Java(TM) SE Runtime Environment (build 16.0.2+7-67)
Java HotSpot(TM) 64-Bit Server VM (build 16.0.2+7-67, mixed mode, sharing)
bash复制代码PS C:\Program Files\Java> .\jdk-16.0.2\bin\java.exe -jar C:\Workspace\Idea\java-test\src\check-default-gc.jar
Get JDK Default GC for jdk16.0.2 - Java HotSpot(TM) 64-Bit Server VM:
G1 Young Generation
G1 Old Generation

记录

可以看到 Oracle 官方在综合考虑之下,JDK8 及以前使用的是 PS Scavenge 和 PS MarkSweep,JDK9 及之后使用的是 G1 收集器

G1 自然不用说,后面推出了 ZGC 可能是由于稳定性考虑没有马上更换,接下来 JDK17 是下一个 LTS,或许会有所更改。

PS Scavenge 和 PS MarkSweep 的选择应该是看重吞吐量高和多线程这两点。由于 CMS 使用标记清除算法,如果用作默认确实不怎么合适。

JDK VersionYoung GCOld GCLTS
JDK5_22PS ScavengePS MarkSweepx
JDK6PS ScavengePS MarkSweepx
JDK7PS ScavengePS MarkSweepx
JDK8PS ScavengePS MarkSweepLTS
JDK9G1 Young GenerationG1 Old Generationx
JDK10G1 Young GenerationG1 Old Generationx
JDK11G1 Young GenerationG1 Old GenerationLTS
JDK12G1 Young GenerationG1 Old Generationx
JDK13G1 Young GenerationG1 Old Generationx
JDK14G1 Young GenerationG1 Old Generationx
JDK15G1 Young GenerationG1 Old Generationx
JDK16G1 Young GenerationG1 Old Generationx
JDK17G1 Young GenerationG1 Old Generationx
JDK18G1 Young GenerationG1 Old Generationx
JDK19G1 Young GenerationG1 Old Generationx

评论