欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JDK默认GC算法是个谜

程序员文章站 2022-06-05 13:18:47
...

JDK默认GC算法是个谜

背景

我们系统采用openjdk:8u212-b04-jdk-stretch作为基础镜像,java -version命令输出:

    openjdk version "1.8.0_212"
    OpenJDK Runtime Environment (build 1.8.0_212-b04)
    OpenJDK 64-Bit Server VM (build 25.212-b04, mixed mode)

从输出信息可以看出是1.8.0版本的OpenJDK。现在因为应用GC的一些问题,我们想知道它的默认GC算法。

下面是查找JDK默认GC算法是一些方法,其中方法一和方法二在我们这个OpenJDK没有用。

方法

方法一,PrintCommandLineFlags

命令行执行:java -XX:+PrintCommandLineFlags -version

理论上输出有开启GC的参数,如-XX:+UseParallelGC。我们这个没有。

方法二,PrintFlagsFinal

命令行执行:java -XX:+PrintFlagsFinal -version|grep Use|grep GC

理论上输出有GC算法开启状态为true。我们这个没有。

方法三,GarbageCollectorMXBean

	public static void main(String[] args) throws InstanceNotFoundException, MalformedObjectNameException, ReflectionException, MBeanException, NullPointerException{
		Object flags = ManagementFactory.getPlatformMBeanServer().invoke(
			    ObjectName.getInstance("com.sun.management:type=DiagnosticCommand"),
			    "vmFlags", new Object[] { null }, new String[] { "[Ljava.lang.String;" });
			for(String f: ((String)flags).split("\\s+"))
			    if(f.contains("GC")) System.out.println(f);
			for(GarbageCollectorMXBean gc: ManagementFactory.getGarbageCollectorMXBeans())
			    System.out.printf("%-20s%s%n", gc.getName(), Arrays.toString(gc.getMemoryPoolNames()));
	}

我们用上面java代码编写一个FindGC.java类,编译成FindGC.class,执行:java FindGC

我们的1.8.0版本OpenJDK的会输出:

    Copy                [Eden Space, Survivor Space]
    MarkSweepCompact    [Eden Space, Survivor Space, Tenured Gen]

我们加上-XX:+UseSerialGC参数,执行:java -XX:+UseSerialGC FindGC

会输出:

    -XX:+UseSerialGC
    Copy                [Eden Space, Survivor Space]
    MarkSweepCompact    [Eden Space, Survivor Space, Tenured Gen]

综上,我们基本可以确定1.8.0版本OpenJDK默认采用的GC算法是SerialGC。

方法四,jmap

jmap -heap PID(PID是某个java进程)会输出Java进程的堆信息,里面有些描述可以辅助推断GC算法。

-XX:+UseSerialGC,输出信息有“Mark Sweep Compact GC”,老年代标识是“tenured generation”。

-XX:+UseConcMarkSweepGC,输出信息有“Concurrent Mark-Sweep GC”,老年代标识是“concurrent mark-sweep generation”。

-XX:+UseParallelGC,输出信息有“Parallel GC with X thread(s)”(X是并发线程数),老年代标识是“PS Old Generation”。

-XX:+UseG1GC,输出信息有“Garbage-First (G1) GC with X thread(s)”(X是并发线程数),老年代标识是“G1 Old Generation”。

我们的1.8.0版本OpenJDK运行jmap -heap PID会输出“Mark Sweep Compact GC”且老年代标识是“tenured generation”,与SerialGC一样,

也基本可以确定默认GC算法是SerialGC。

总结

JDK开发者并没有提供直接的工具查看默认GC算法,我们只能通过一些辅助手段来确定。

参考

Is there a way to tell which GC algorithm the JVM is currently using

How to determine which GC I use?

Java 8最快的垃圾收集器是什么?