Scan the qr code below or search wechat public account Rookie Fei Yafei, you can follow wechat public account, read more Spring source code analysis, Java concurrent programming, Netty source code series and MySQL working principle articles.

Wechat official account

1. Introduction

As the JDK has been updated, the garbage collector has become more efficient. Every JDK update inevitably includes an update to the garbage collector, and as of now, in the latest JDK14 release, the latest garbage collector is ZGC.

Since the development of garbage collector, there have been many garbage collectors, such as: Serial, ParNew, Parallel Scavenge, SerialOld, CMS, Parallel Old, G1, Shenandoah, ZGC, etc., although G1 and ZGC are the more popular ones at the moment, But those classic garbage collector we will also be necessary to know how they work, on the one hand, because of still have a lot of systems use are JDK8 and the following version, the version there are a lot of systems are used by default in the classic garbage collector, understand their principle, convenient we tune about it, on the other hand is to interview, After all, the garbage collector is a popular interview topic.

The Serial, ParNew, Parallel Scavenge, SerialOld, CMS, Parallel Avenge avenge, SerialOld, CMS, And Parallel Avenge avenge. In the next article, WE will introduce how G1, Shenandoah and ZGC work.

2. Performance indicators

Before introducing the garbage collector, let’s look at some common metrics for measuring garbage collectors.

The first is “throughput”, which describes how long the user thread executes over the total elapsed time (total elapsed time = user thread time + garbage collector thread execution time). The higher the throughput, the higher the resource utilization of the system.

Then there is the “pause time”, which is the amount of time that the GC thread causes the user thread to pause during execution. If the pause time is longer, the user thread will be stuck for longer and the user experience will be worse, so we want the pause time to be as short as possible.

Another metric is “memory usage”, because the garbage collector also needs to use a certain amount of memory during its execution, and of course we expect the memory usage to be as low as possible, especially if the server memory configuration is low. If the server has high resource configuration and large memory, a higher memory usage is acceptable.

In general, “throughput and low latency (pause time) are opposites”, you can’t do both at the same time, and if you want low latency, throughput will drop; If high throughput is pursued, the pause times become longer. However, with the continuous development of garbage collectors, more and more garbage collectors are based on the principle of “in the case of ensuring high throughput, as far as possible to pursue low latency”, to implement garbage collectors.

3.Serial

Serial is a new generation garbage collector. It is a single-threaded, Serial garbage collector that uses a replication algorithm. Its single thread does not just mean that it is single-threaded or single-processor when garbage collection is performed, but that it needs to suspend all other threads when garbage collection is performed, resulting in STW.

Serial is the default garbage collector when the JVM is in client mode and has the advantage of being simple and efficient. In memory-constrained environments, Serial garbage collector takes up less memory than other garbage collectors. For single-processor scenarios, Serial processors are more efficient because they are single-threaded, eliminating contention between threads for resources.

When -xx :+UseSerialGC is used, the garbage collector of the Old age is Serial Old when Serial garbage collector is enabled.

4.Serial Old

Serial Old, like Serial, is a Serial garbage collector that executes single-threaded, except that Serail Old collects Old regions using a mark-compress algorithm. The same phenomenon occurs when garbage is collected.

When the JVM is in “client” mode, Serial Old is usually used in conjunction with Serial garbage collector, where Serial collects the Cenozoic region and Serial Old collects the old-age region. The schematic diagram of Serial and Serial Old is as follows.

Serial/Serial Old with garbage collection schematic

When the JVM is in “server” mode, Serial Is used in conjunction with the Parallel Exploiter. Second, as a fallback to the CMS garbage collector (more on this later). Serial Old can also be used with the ParNew garbage collector, but this combination has been removed starting with JDK9.

5.ParNew

ParNew is a multi-threaded version of Serial garbage collector, which is a parallel garbage collector that allows multiple garbage collection threads to collect garbage in parallel, using a replication algorithm. For example, the parameter “-xx :ParallelGCThreads” can be used to specify the number of concurrent garbage collection threads. By default, the number of garbage collection threads is equal to the number of processors. On a single-processor system, ParNew does not necessarily perform better than Serial because thread switching requires additional CPU resources.

Garbage collection with ParNew can be turned on with the argument “-xx :+UseParNewGC”.

ParNew can be used with Serial Old or CMS. However, as of JDK9, the combination of ParNew and CMS has been removed and CMS has been marked as Deprecated. The complete removal of CMS from JDK14 leaves ParNew in the awkward position of not being able to work with Serial Old in older versions or CMS in the future, and the garbage collector is bound to disappear into history.

ParNew/Serial Old with garbage collection schematic

6.Parallel Scavenge

The Parallel Scavenge avenge is a “new generation of insane” garbage collector. The Parallel Avenge avenge is a “through-first” garbage collector. This is ideal for scenarios where you want to maximize CPU utilization, complete the program’s computation tasks as quickly as possible, and place little emphasis on user interaction.

The Parallel Insane provides two parameters to accurately control throughput, the “MaxGCPauseMillis” and the “GCTimeRatio”.

MaxGCPauseMillis represents the maximum pause time of the system for each garbage collection. If this parameter is configured, the JVM will try to keep the pause time within MaxGCPauseMillis for each garbage collection. This parameter is not set as small as possible. If it is set as small as possible, the JVM may choose to reduce the size of the new generation area in order to keep the pause time within MaxGCPauseMillis, since the recovery time of 300M space is certainly less than 500M. When the JVM shrinks the memory area of the new generation, garbage collection takes place more frequently, resulting in lower system throughput. In general, we cannot accurately control the pause time of each garbage collection, so this parameter should be used with caution. If you are not careful, an unreasonable configuration may backfire.

GCTimeRatio indicates the ratio of time consumed by each GC (GCTimeRatio = user thread run time/GC thread run time), for example: If the value of the GCTimeRatio parameter is set to 19, the GC runs 5% of the time (1 /(1+19)). The JVM uses this parameter to control system throughput.

The JVM also provides a parameter called “UseAdpativeSizePolicy” that allows the JVM to “dynamically adjust” the size of the new generation (Eden, S0, S1) and the old generation based on how the system is running. We only need to set the most basic memory parameters and either MaxGCPauseMillis (maximum pause time) or GCTimeRatio (target throughput). There is no need to set parameters such as -xx :Xmn and -xx :SurvivorRatio. The JVM will dynamically adjust these parameters based on the information monitored by the system at runtime. The Parallel Insane supports dynamic adaptation strategies, which is another important difference from the ParNew collector.

7.Parallel Old

The Parallel Old is an older version of the Parallel Avenge collector, which supports Parallel execution through multiple threads and is based on the mark-compress algorithm. The Parallel Collector was only used with Serial Old, not the CMS garbage collector, before the Parallel Old Collector was invented in JDK6. The Parallel Insane is not compatible with the underlying frameworks of the CMS, Serial, and ParNew collectors. The Serial Old garbage collector is a single-threaded garbage collector that performs poorly on multiple processors and wastes the Parallel Insane, so before Parallel Old was invented, The Parallel Avenge has always been the exploiter. The Parallel insane and Parallel Old are the default garbage collector in JDK8.

Parallel Avenge /Parallel Old garbage recycling schematic

8.CMS

CMS, which stands for concurrent-mark-sweep and translates to Concurrent Mark Sweep, is a garbage collector that “targets low pause times” and features low latency. The working principle of CMS is roughly divided into four steps: initial marking, concurrent marking, re-marking, and concurrent cleaning. To enable the CMS garbage collector, use “-xx :+UseConcMarkSweepGC”.

  1. “Initial marking” refers to marking only objects directly associated with GC Roots, a process that requires suspending all user threads, thus generating STW. Since this step only marks objects that are directly associated with GC Roots, this step takes a very short time, resulting in a very short pause time.
  2. Concurrent markup. This step starts with the object directly associated with the GC Roots and traverses the entire object graph reference chain. This process is performed concurrently by the GC thread and the user thread, thus causing no STW. This step takes a long time because it needs to traverse the reference chain of all objects. Since it does not cause STW, it does not matter if it takes a long time.
  3. “Relabeling.” In the concurrent marking phase, the user thread is still running, thus changing the reference relationship between objects, so in the re-marking phase, the result of the concurrent marking is corrected. Re-mark as survivable objects objects that are suspected to be garbage but are not. This step requires the suspension of all user threads, resulting in STW, which takes longer than the initial tagging phase, but much less than the concurrent tagging phase.
  4. Concurrent cleanup. In this phase, the garbage collector thread and the user thread execute concurrently, and the garbage collector thread cleans up the garbage object. This step takes a long time, but does not cause STW.

On the whole, the CMS garbage collector only causes user threads to pause during the initial marking and re-marking phases, but these two steps take a short time, so the CMS garbage collection on the whole is low latency. The schematic diagram is as follows.

CMS garbage collection diagram

8.1 Advantages and disadvantages of CMS and parameter tuning

The CMS garbage collector has the advantage of low latency, which makes it particularly suitable for sites or systems that expect fast responses and short pause times to improve the user experience.

The shortcomings of CMS are also obvious. First, “sensitive to CPU resources”. Since the garbage collection thread needs to execute concurrently with the user thread, it will compete for CPU resources, resulting in a decrease in system throughput. We can control the number of garbage collection threads with the parameter “-xx :ParallelGCThreads”. The default value is “(number of processor cores +3)/4”.

Second, CMS “creates floating garbage”. While CMS is collecting garbage, the user thread is also performing garbage collection. During this process, the user thread may also generate new garbage that will not be collected by CMS during this garbage collection. This garbage is called “floating” garbage. Also it is because the trash thread and the user threads execute simultaneously, so the CMS garbage collector, not garbage collected until heap memory is used up, it needs to be reserved for the system part of the memory for user threads running, so the CMS is usually when the heap memory usage to reach a certain threshold, it triggers garbage collection.

The threshold in JDK5, the default value is 68%, the JDK6 has later, the threshold of the default value is increased to 92%, we can through the parameter “- XX: CMSInitiatingOccupancyFraction” manually. In practice, if the memory usage of the system is growing slowly, this threshold can be appropriately set to be higher to reduce the frequency of garbage collection to improve system performance. However, if the value is too large, there are additional problems. When the value is too large, that is, the memory is about to be used up. At this point, since the user thread is still running, if the memory needs to be allocated for a relatively large object and the remaining memory is insufficient, A “Concurrent Mode Failure” log is displayed indicating a Concurrent garbage collection Failure, and the JVM is forced to initiate an alternative, freezing the user thread and using the Serial Old garbage collector for the Old garbage collection. To a certain extent, System performance may be degraded.

Third, CMS “generates garbage debris.” CMS uses a mark-sweep algorithm, so memory fragmentation can occur, which can affect program performance. If you allocate memory for a large object and there is no room in memory for that object, the JVM will have to trigger a Full GC, causing the program to STW. In order to reduce memory fragmentation, CMS developers provide a switch that, when turned on, causes the garbage collector to defragment memory after the Full GC has completed. This parameter is: “- XX: + UseCMSCompactAtFullCollection”, “+” said open the switch.

This switch solves the problem of memory fragmentation, but the low latency of a CMS can be compromised if defragmentation is performed every time after Full GC, and each defragmentation needs to suspend the user thread, causing STW. Therefore the CMS developers also provides another parameters: “- XX: CMSFullGCsBeforeCompaction”, how many times is the meaning of this parameter means that when a Full GC, memory again.

8.2 DEVELOPMENT status and future of CMS

CMS is a garbage collector for the old age, it needs to be used with the new generation of garbage collector, and can only be used with Serial, ParNew these two new generation of garbage collector. Before G1 garbage collector, CMS was the only concurrent, low-latency garbage collector, which was widely used. However, it was later broken by G1 garbage collector, which also has concurrent cleaning, low latency, but is many times more efficient than CMS. In JDK9, CMS has been marked as “Deprecated” and is now being Deprecated. In JDK14, CMS has been removed completely, becoming the first garbage collector to be completely abandoned.

9. To summarize

The article describes the Serial, ParNew, Parallel Exploiter, SerialOld, CMS, And Parallel Avenge in detail, and uses a graphic to summarize the relationship between them. It should be noted that the combination of ParNew and Serial Old and Serial and CMS was removed in JDK9, and CMS was marked Deprecated and removed completely in JDK14.

Garbage collector collocation combination

Reference 10.

  • Understanding the Java Virtual Machine in Depth. 3rd edition

Related to recommend

  • An interview question that you don’t even know why you read the answer
  • Garbage tag algorithm for garbage collection
  • JVM family of garbage collection algorithms
  • JVM family of STW, parallel and concurrency, safe point and safe zone
Wechat official account