GC plays (2) Detailed explanation of the characteristics of the garbage collector

Continue to create, accelerate growth! This is the second day of my participation in the "Nuggets Daily New Plan · June Update Challenge", click to view the details of the event

Abstract
GC log is an important basis for judging whether there is a fault in Java application memory. This small series of "GC Playing" is expected to enable zero-based readers to quickly understand important concepts related to GC, and finally master the analysis method of GC logs.
The second article "Detailed Explanation of Garbage Collector Features" aims to sort out various garbage collectors under JDK1.8, and understand the different names of different garbage collectors for the concepts of old and new generations.

1 Classification of garbage collectors

The garbage collector of the JVM is a specific implementation of garbage cleaning and memory recovery algorithms. The garbage collector included in the JVM is shown in the following figure (based on JDK1.8):

The lines in the figure represent that the garbage collectors can be used in conjunction with each other.

For the 7 types of garbage collectors in the figure, we can make the following simple understanding:

  • Serial: Serial collector, is a single-threaded collector.

  • Parallel: Parallel collector, which performs well under multi-core CPUs; ParNew is a multi-threaded version of Serial; Parallel Scavenge is similar to ParNew, and pursues more controllable throughput.

Throughput
Throughput is the ratio of the time the CPU spends running user code to the total CPU time spent.
Throughput = User Code Running Time / (User Code Running Time + Garbage Collection Time)

  • CMS (Concurrent Mark Sweep): Based on the concurrent mark sweep algorithm, application threads and GC threads are executed alternately to minimize application pause time, but it will affect the overall throughput and performance of the application.

  • G1: The G1 collector can perform Mixed GC, similar to ParNew for the collection of the young generation, and similar to CMS for the collection of the old generation, but compared to CMS, G1 does not generate memory space fragmentation, and a clear maximum pause time can also be specified. .

2 JVM parameters related to the garbage collector

We can specify which combination of garbage collectors the application uses via JVM arguments:

JVM 参数 新生代垃圾回收器 老年代垃圾回收器
-XX:+UseSerialGC Serial Serial Old
-XX:+UseParallelGC
(同 -XX:+UseParallelOldGC )
Parallel Scavenge Parallel Old
-XX:+UseParNewGC ParNew Serial Old
-XX:+UseConcMarkSweepGC ParNew CMS + Serial Old
-XX:+UseG1GC G1 G1

3 如何查看默认的垃圾回收器

通常情况下,我们没有特意去指定应用使用哪种垃圾回收器(实际上好像也确实没有这个必要)。

查阅网上的资料, JDK1.8 默认使用 Parallel Scavenge + Parallel Old 。出于好奇,很想实际确认一下这个结论,结果因为服务器环境的问题(一开始选择的是一台单逻辑 CPU 的虚机,各种方法各种不正常,后来换了一台 8 逻辑 CPU 的虚机就与理论一致了),绕了很多弯,采了很多坑。现将所实践的 6 种方法记录如下(突然想起了《孔乙己》中茴香豆的“茴”字有四种写法):

查看逻辑 CPU 数量:

cat /proc/cpuinfo| grep "processor"| wc -l
复制代码

3.1 使用 -XX:+PrintCommandLineFlags

使用 -XX:+PrintCommandLineFlags 打印命令行参数,可以在参数中看到默认使用的垃圾回收器:

java -XX:+PrintCommandLineFlags -version
复制代码

图中显示的 -XX:+UseParallelGC 与理论上的 Parallel Scavenge + Parallel Old 一致。

单逻辑 CPU 环境采坑: 使用 -XX:+PrintCommandLineFlags 所打印出的命令行参数,没有使用垃圾回收器的相关信息。

3.2 使用 -XX:+PrintFlagsFinal

使用 -XX:+PrintFlagsFinal 查看 GC 垃圾回收器的开启状态:

java -XX:+PrintFlagsFinal -version | grep Use | grep GC
复制代码

图中显示 UseParallelGCUseParallelOldGC 为 'true' ,与理论上的 Parallel Scavenge + Parallel Old 一致。

单逻辑 CPU 环境采坑: 使用 -XX:+PrintFlagsFinal 所打印出的 6 种垃圾回收器的开启状态均为 false

3.3 使用 jinfo -flag

使用 jinfo -flag 来逐一确认应用是否启用了指定的垃圾回收器:

jinfo -flag UseXXXGC 应用端口号
复制代码

图中显示 UseParallelGCUseParallelOldGC 为 '+' 号开启,其余 4 种垃圾回收器的 JVM 参数为 '-' 号禁用,与理论上的 Parallel Scavenge + Parallel Old 一致。

单逻辑 CPU 环境采坑: 使用 jinfo -flag 得到的所有的 UseXXXGC 参数均为 '-' 号禁用状态。

3.4 使用 jmap -heap

分析 jmap -heap 命令的输出结果,通过关键字可以明确具体的垃圾收集器类型:

jmap -heap 应用端口号
复制代码

首先总结各类垃圾回收器对应的 jmap -heap 信息特征:

JVM 参数 对于垃圾回收器的描述 新生代的别称 老年代的别称
-XX:+UseSerialGC Mark Sweep Compact GC New Generation tenured generation
-XX:+UseParallelGC Parallel GC with X thread(s) PS Young Generation PS Old Generation
-XX:+UseParallelOldGC Parallel GC with X thread(s) PS Young Generation PS Old Generation
-XX:+UseParNewGC using parallel threads in the new generation.
Mark Sweep Compact GC
New Generation tenured generation
-XX:+UseConcMarkSweepGC Concurrent Mark-Sweep GC New Generation concurrent mark-sweep generation
-XX:+UseG1GC Garbage-First (G1) GC with 1 thread(s) G1 Young Generation G1 Old Generation

然后我们对比一下未明确指定垃圾回收器的应用的信息,特征符合 UseParallelGC (同 UseParallelOldGC ),与理论上的 Parallel Scavenge + Parallel Old 一致:

单逻辑 CPU 环境采坑: 使用 jmap -heap 得到的信息特征符合 UseSerialGC ,与理论上的 Parallel Scavenge + Parallel Old 不一致。

3.5 使用 GarbageCollectorMXBean

通过 java.lang.management.GarbageCollectorMXBean 类可以获取应用的垃圾回收器相关信息。

首先编写一个 Java 文件,内容如下:

import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.util.Arrays;

import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;

public class PrintGCInfo {

	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()));
	}

}
复制代码

通过 javac 编译后,再执行,即可得到垃圾回收器相关信息:

图中显示的 -XX:+UseParallelGC 与理论上的 Parallel Scavenge + Parallel Old 一致。

明确指定各类垃圾回收器,再运行此类,我们就可以得到各类特征信息:

Single logic CPU environment mining pit:java.lang.management.GarbageCollectorMXBean The information characteristics obtained through are consistent UseSerialGC, which are inconsistent with the theoretical Parallel Scavenge + Parallel Old.

3.6 Using GC logs

Use -XX:+PrintGCDetailsto generate detailed GC logs.

java -Xms512m -Xmx2g -XX:+PrintGCDetails -Xloggc:gc.log -jar xxx.jar
复制代码

At the beginning of the log, the JVM operating parameters will be printed, including the type of garbage collector used, which is consistent -XX:+UseParallelGCwith the theoretical Parallel Scavenge + Parallel Old.

With the -XX:+UseXXXGCoption , we can get the GC logs generated by different garbage collectors. The descriptions of the old generation and the new generation in these logs are different. The summarized characteristic information is as follows:

JVM arguments Another name for the new generation in the log Another name for the old age in the log
-XX:+UseSerialGC DefNew Tenured
-XX:+UseParallelGC PSYoungGen ParOldGen
-XX:+UseParallelOldGC PSYoungGen ParOldGen
-XX:+UseParNewGC ParNew Tenured
-XX:+UseConcMarkSweepGC ParNew CMS
-XX:+UseG1GC There is no dedicated Cenozoic depiction, there are Eden and Survivors There is no special description of the old age, there is Heap

Single logical CPU environment mining pit: No information about using the garbage collector like -XX:+UseXXXGCthis .


The above is the introduction of the characteristics of different garbage collectors. The next article will focus on the generation and analysis of GC logs.

Guess you like

Origin juejin.im/post/7103912966776422436