JDK默认GC算法是个谜
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
推荐阅读