“This is the fifth day of my participation in the November Gwen Challenge. See details of the event: The Last Gwen Challenge 2021”.

Although common garbage collection algorithms are fixed, how memory collection works is determined by the GC collector used by the virtual machine, and there is often more than one GC collector in a virtual machine, they also use different GC algorithms. Let’s take a look at seven GC collectors in HotSpot. If the garbage collection algorithm is the methodology of memory collection, then the garbage collector is the concrete implementation of memory collection.

For common garbage collection algorithms, see this article: Common JVM garbage Collection Algorithms in Java.

@[toc]

1 Overview of garbage collector

The common garbage collector for the HotSpot VIRTUAL machine is as follows:

The figure above shows seven collectors acting on different generations, and if there is a line between the two collectors, they can be used together. The region in which the virtual machine is located indicates whether it belongs to the new generation collector or the old generation collector. Let’s look at a schematic of the seven garbage collectors.

1.1 Default garbage collector

To view the default setting commands:

java -XX:+PrintCommandLineFlags -version

View default garbage collector details command to identify garbage collectors by new generation and old generation names

java -XX:+PrintGCDetails -version

Better positioning of which garbage collectors are used

java -XX:+PrintFlagsFinal

My JDK1.8 information is as follows

The PSYoungGen insane is a new generation managed by the Parallel Insane collector, and the ParOldGen is an older generation managed by the Parallel Old.

Java -xx :+PrintFlagsFinal

Default garbage collector:

To be insane, insane, insane, insane, insane, insane, insane, insane Default garbage collector G1

1.2 Concurrency and parallelism in the garbage collector

Concurrency and parallelism. Both of these terms are concepts in concurrent programming, and in the context of talking about the garbage collector, they can be explained as follows.

Parallel: Multiple garbage collection threads work in Parallel while the user thread is still in a waiting state.

Concurrent: The execution of both the user thread and the garbage collector thread at the same time (but not necessarily in parallel and may occur alternately), with the user program continuing to run while the garbage collector is running on another CPU.

2 Introduction to garbage collector

2.1 Serial Collector

Serial is a basic garbage collector that uses a replication algorithm and was the only garbage collector in the younger generation prior to JDK1.3.1. Serial garbage collector means that Serial is a single-threaded collector that not only uses one CPU or one thread to complete garbage collection, but must suspend all other worker threads while garbage collection is in progress. This phenomenon is called STW (Stop-the-world).

STW is automatically initiated and completed by the virtual machine in the background. It stops all the threads that the user normally works without being visible to the user, which is unacceptable for many applications.

The Serial garbage collector, while suspending all other worker threads during garbage collection, is simple and efficient, achieving the highest single-thread garbage collection efficiency for a limited single-CPU environment without the overhead of thread interaction. So Serial garbage collector is still the default young-generation garbage collector for Java virtual machines running in Client mode.

For more interactive applications, this garbage collector is unacceptable. This collector is not typically used in Javaweb applications.

The young generation adopts copy algorithm, and the Old generation adopts Serial Old algorithm.

Schematic diagram of Serial and Serial Old:

2.1.1 Related Parameters

-xx :+UseSerialGC specifies that both the new generation and the Old generation are using the Serial garbage collector, i.e. Serial+Serial Old.

2.2 Serial Old Collector

Serial Old is an older version of the Serial collector, which is also a single-threaded collector using a mark-tidy algorithm. The main significance of this collector is also for the use of virtual machines in Client mode. If in Server mode, it has two main uses: The Application is used in JDK 1.5 and earlier with the Parallel Scavenge collector, and as a fallback to the CMS collector when Concurrent Mode failures occur in Concurrent collections. Both of these will be covered in more detail later.

2.2.1 Related Parameters

-xx :+UseSerialGC specifies that both the new generation and the Old generation are using the Serial garbage collector, i.e. Serial+Serial Old.

-xx :+UseParNewGC The new generation uses ParNew. The Old generation uses Serial Old by default.

-xx :+UseParallelGC Insane, use Serial Old.

2.3 ParNew collector

The ParNew collector is essentially a multithreaded version of the Serial collector, a parallel garbage collector. Except for the use of multiple threads for garbage collection, the two collectors behave exactly the same as the Serial collector, which also share a considerable amount of code in implementation. The working process of the ParNew collector is shown below:

The ParNew collector is the preferred next-generation collector for many virtual machines running in Server mode, and for a non-performance related but important reason, in addition to the Serial collector, Only ParNew currently works with the CMS collector (because the Parallel Avenge (as well as G1) does not use the traditional GC collector code framework and is implemented independently; The other collectors share some of the framework code).

2.3.1 Related Parameters

Due to the overhead of multi-threaded interactions on a single CPU, the ParNew collector may not perform better than the Serial collector in a single-CPU environment. The default number of collection threads is the same as the number of cpus. You can limit the number of garbage collection threads by using -xx :ParallelGCThreads.

-xx :+UseConcMarkSweepGC The new generation uses ParNew, the old generation uses CMS.

-xx :+UseParNewGC The new generation uses ParNew. The Old generation uses Serial Old by default.

2.4 Parallel Scavenge

The Parallel Scavenge collector is a new generation collector that uses the replication algorithm. The Parallel Scavenge collector is a Parallel multithreaded collector, the default Java1.8 new generation garbage collector.

It focuses on achieving a manageable throughput (Thoughput, the amount of time the CPU takes to run user code/total CPU consumption, i.e. Throughput = run user code time /(run user code time + garbage collection time)), which takes precedence over throughput. High throughput can be most efficient use of CPU time, as soon as possible to complete the program of computing tasks, mainly is suitable for the operation and don’t need too much in the background of interaction with the user task, that is to say the task after allowing for a long time the GC (good response speed can improve the user experience, such a scenario requires the shorter GC, shorter SWT, CMS works better at this point).

The adaptive conditioning strategy is also an important distinction between the Parallel Avenge collector and the ParNew collector, which is often referred to as the “through-first” collector.

2.4.1 Related Parameters

The Parallel Scavenge collector provides two parameters to control throughput precisely: the -xx :MaxGCPauseMillis parameter, which controls the maximum garbage collection pause time, and the -xx :GCTimeRatio parameter, which directly sets the throughput size.

-xx: the MaxGCPauseMillis parameter allows a value greater than 0 milliseconds, and the collector will do its best to ensure that memory reclamation takes no longer than the set value. GC pause time comes at the expense of: throughput and new generation space for system, the new generation down some collected 300 MB Cenozoic must faster than collect 500 MB, it is also directly contributing to the garbage collection occurs more frequently, the original 10 seconds to collect a pause at a time, 100 milliseconds, now 5 seconds collection, pause every time 70 milliseconds at a time. Pause times did go down, but so did throughput.

-xx: the value of the GCTimeRatio parameter should be an integer greater than 0 and less than 100, which is the ratio of the garbage collection time to the total time, equivalent to the inverse of the throughput. If you set this parameter to 19, the maximum allowed GC time is 5% of the total time (1/ (1+19)), and the default is 99, which is the maximum allowed garbage collection time of 1% (1/ (1+99)).

The Parallel Insane collector also has a parameter -xx :+UseAdaptiveSizePolicy. When the Parallel Insane collector is on, There is no need to manually specify the size of the Cenozoic (Xmn), Eden and Survivor area ratio (- XX: SurvivorRatio), promotion of age old s (- XX: PretenureSizeThreshold) detail parameters, such as, The virtual machine collects performance monitoring information based on the current system performance and adjusts these parameters dynamically to provide the most appropriate pause times or maximum throughput. This adjustment mode is called GC Ergonomics.

-xx :+UseParallelGC Insane, use Serial Old.

-xx :+UseParallelOldGC insane, ParallelOld.

2.5 Parallel Old collector

Older versions of the Parallel Insane, usually used in combination to chase CPU throughput. The collector, which was only introduced in JDK 1.6, is executed in parallel by multiple GC threads at garbage collection time and suspends all user threads using a “mark-collation” algorithm. Therefore, since garbage collection and user threads are not executed in parallel during GC, they are throughput seeking garbage collectors.

2.5.1 Related Parameters

-xx :+UseParallelOldGC insane, ParallelOld.

2.6 CMS Collector

The CMS (Concurrent Mark Sweep) collector is distinguished from the Parallel Scavenge and Parallel Old collector in that it is a collector whose goal is to obtain the shortest recovery pause time. At present, a large part of Java applications are concentrated on the server side of Internet sites or B/S systems. These applications pay special attention to the response speed of services and hope to have the shortest system pause time to bring users a better experience. The CMS collector is a good fit for such applications.

2.6.1 Working procedure of the CMS collector

The CMS collector is generally based on the “mark-clear” algorithm, and its specific operation process is more complex than the previous several collectors, including:

  1. The initial mark (CMS-initial-mark), which marks all root, causes STW;
  2. Concurrent mark (cmS-concurrent-mark), which runs concurrently with the user thread;
  3. Preclean (cmS-concurrent-preclean), running at the same time as the user thread;
  4. (CMS-concurrent-abortable-preclean) Preparing for and controlling the pause time before cleaning and running at the same time with the user thread;
  5. CMS-remark, which corrects concurrent marked data, will result in STW.
  6. CMS-concurrent-sweep, which cleans garbage, runs concurrently with the user thread;
  7. Concurrent reset: Waits for the next CMS trigger (cms-concurrent-reset) to run concurrently with the user thread.

The main steps are: CMS Initial mark, CMS Concurrent mark, CMS remark, and CMS Concurrent sweep.

Due to The tag-clearing algorithm, The initial tagging and re-tagging steps still need to “Stop The World”. Initial marking only marks GC Roots objects, which is very fast. The concurrent marking stage is the process of GC RootsTracing, while the re-marking stage is to correct the mark records of those objects whose marks change due to the continued operation of the user program during the concurrent marking. The pause time in this phase is generally slightly longer than in the initial tagging phase, but much shorter than in concurrent tagging.

Because the collector thread, which is the longest concurrent marking and concurrent cleanup process, can work with the user thread, the CMS collector, as a whole, executes its memory reclamation process concurrently with the user thread and can be considered a concurrent garbage collector.

2.6.1.1 Initial flag

This is one of two stop-the-world events in CMS. This step marks alive objects and has two parts:

  1. Mark all GC Roots objects in the old age, node 1 in the figure below;

  2. Nodes 2 and 3 in the figure below mark objects of the old age referenced by living objects in the young generation (referring to objects of the reference type that are alive in the young band and refer to objects in the old age).

In order to speed up this stage processing speed, reduce the pause time, can open the initial tag parallelization – XX: + CMSParallelInitialMarkEnabled, large parallel marks the number of threads at the same time, the number of threads do not exceed the CPU’s auditing.

2.6.1.2 Concurrency flag

The concurrent tagging phase, which is performed with the application, does two things:

  1. Starting with the GC Roots objects marked in the “initial tag” phase, all objects that can be referenced are traversed to find all surviving objects;
  2. In the concurrent stage, the cards where the new generation is promoted to the old age, the objects directly assigned in the old age, and the objects whose reference relationship changes in the old age are marked as dirty. In the subsequent stage, only the objects of these dirty cards are scanned, avoiding scanning the whole old age in the re-marking stage.

The concurrent marking stage is only responsible for marking the Card whose reference has been changed as Dirty, and is not responsible for processing; Because this phase is concurrent with the user thread, a concurrent mode failure can occur.

2.6.1.3 pre-cleaning

This phase is used to process unmarked live objects due to reference changes in the previous phase. It scans all cards marked as Dirty. As shown in the figure below, during the concurrent cleanup phase, node 3 refers to node 6; The card on node 3 is marked as Dirty.

Finally, mark 6 as alive and the Dirty area disappears, as shown below:

2.6.1.4 Pre-cleaning can be interrupted

The purpose of this phase is to reduce the workload of re-marking and reduce the pause time. This phase can be cancelled by using the -xx: -cmSPRecleaningEnabled parameter to indicate that no elimination is performed. This phase does two things (repeat the previous phase) and can be terminated:

  1. Scan objects in the DirtyCard
  2. Handles old objects referenced by the new generation

Exit conditions are:

  1. 5 seconds exit CMSMaxAbortablePrecleanTime parameter control
  2. Eden area achieve CMSScheduleRemarkEdenPenetration parameters configuration values (50%) by default
  3. CMSMaxAbortablePrecleanLoops control the number of scanning (the default is 0, not quit)

Because remarking is CPU-exclusive, a pause can be long if a remarking is triggered immediately after a new generation GC occurs. And interruptible pre-cleaning maximum duration for 5 seconds, can last for 5 seconds, another reason to expect it can occur in five seconds a Young, GC, and pre-cleaning Young generation of reference (pre-cleaning is concurrent), making the next phase of the mark phase, scan with reference to the old s Young time reduced; The overlap between Cenozoic GC and relabeling is avoided to the greatest extent and the relabeling pause time is minimized.

2.6.1.5 Final relabel

The final tagging is also called re-tagging, and this stage leads to a second stop the word phase, in which the task is to finish tagging all surviving objects in the entire aged generation. The range of memory to be relabelled is the entire heap, containing both Young Gen and Old Gen.

If objects in the old generation are referenced by objects in the new generation, they will be regarded as living objects. Even if objects in the new generation are unreachable, unreachable objects will be used as the “GC root” of CMS to scan the old generation. Therefore, for the old generation, objects of the new generation that refer to objects of the old generation will also be regarded as “GC ROOTS” by the old generation.

If this phase takes a long time, you can add the parameter ** -xx :+CMSScavengeBeforeRemark**, and perform a Young GC before re-marking to collect the objects of the Young band that are no longer useful, and put the objects into the survival band or promoted to the old age, so that when the Young band is scanned again, Only objects in the survival zone need to be scanned. The survival zone is usually very small, which greatly reduces the scanning time.

Since the previous pre-processing stage is executed concurrently with the user thread, many changes may have taken place in the reference of the young object to the old age. At this time, it will take a lot of time to process these changes in the remark stage, which will lead to a long stop of the word. So CMS usually tries to run Final Remark when the young generation is clean enough. The parallel collection can also be enabled: -xx :+ CMSPARallelEnabled.

2.6.1.6 Concurrent Clearing

This phase focuses on clearing unmarked objects and reclaiming space.

Because the CMS concurrent cleanup phase user threads are still running, new garbage is naturally generated as the program runs. This part of garbage is generated after the marking process, and the CMS cannot dispose of it in the current collection, so it has to be cleaned up in the next GC. This part of garbage is called “floating garbage”.

2.6.1.6 Concurrent Reset

This phase is the final phase to reset the structure of the CMS’s data in preparation for the next GC.

2.6.2 Points to Pay attention to when using A CMS

2.6.2.1 Low Throughput

Because the CMS has the additional overhead of thread switching in parallel with user threads during GC, CPU throughput is not as high as stopping all user threads during GC

2.6.2.2 Reduce the pauses in the Remark Phase

Generally, 80% of THE GC time of CMS is in the remark phase. If the pause time of the remark phase is long, you can add this parameter: -xx :+CMSScavengeBeforeRemark Performs a Young GC before the remark operation to reduce the invalid reference of the Young generation to the old generation and the cost of remark.

2.6.2.3 Memory Fragmentation Problem

CMS is based on the tag – clear algorithm, CMS will only delete useless objects, not to memory compression, can lead to fragmentation, are too much, space debris will bring a lot of trouble to the large object allocation, often appear old s also has the very big space remaining, but unable to find a large enough contiguous space to allocate the object, The Full GC had to be triggered again in advance, and here (in the JDK 8 scenario) the Full GC uses the Serial GC, which is inefficient.

In order to solve this problem, a CMS provides a collector – XX: + UseCMSCompactAtFullCollection switch parameters (the default is open), is used to hold the CMS collector to open when Full GC memory fragments merging sorting process, The process of defragmenting is not concurrent, the space fragmentation problem is gone, but the pause time has to be long.

This time we need to use this parameter: – XX: CMSFullGCsBeforeCompaction = n. This is how many more Full GC will be performed after the last CMS concurrent GC. The default is 0, which means that after every Full GC (flag clearance), compression occurs. If the CMSFullGCsBeforeCompaction configured for 10, you will make the above said the first condition of every 10 times to do a real Full GC compression.

2.6.2.3 concurrent mode failure

This exception occurs while the CMS is collecting. During the process of CMS GC, the business thread is also running. When the space of the Young band is full, it is necessary to put the surviving objects into the old age when the space of the old age is insufficient. At this time, CMS does not have the opportunity to recycle the garbage generated by the old age band, or during the time of Young GC, the space of the new generation is not enough. Need to put into the old age, and the old age also can not put the generation.

There are two parameters for setting the trigger time of the CMS:

  1. -XX:+UseCMSInitiatingOccupancyOnly
  2. -XX:CMSInitiatingOccupancyFraction=70

– XX: CMSInitiatingOccupancyFraction = 70 refers to set the CMS on began to GC in memory usage rate of 70%.. The CMS collector defaults to 68% under JDK 1.5, and the startup threshold for the CMS collector has been raised to 92% in JDK 1.6.

– XX: + UseCMSInitiatingOccupancyOnly if not specified, but the recovery by setting threshold CMSInitiatingOccupancyFraction, only used for the first time the JVM Settings, subsequent automatic adjustment will lead to the parameters of the above doesn’t work.

Why do we have these two parameters?

Because the user thread in garbage collection phase still need to run, it will also need to set aside enough memory space for user thread is used, therefore the CMS collector can’t wait for old age is almost like other collector is completely filled to be collected, need to set aside part of space to provide operational use concurrent collection program.

Five stages before CMS are markers of live objects, in addition to the initial mark “and” to “tag” stage will SWT, the other three stages are run with user thread, can appear such circumstance GC thread is marked live objects, user threads to raise new objects of old age, at the same time the cleanup has yet to start, Old Gen runs out of room to hold any more objects, which results in a Concurrent mode failure and then a degenerate Full GC– using the serial collector to reclaim the entire heap, resulting in very long pauses.

Note: CMSInitiatingOccupancyFraction parameter to set a reasonable value, set up big, will increase the frequency of concurrent mode failure occurs, set small, and can increase the frequency of CMS, so according to the running situation of the application to select a reasonable value. If this parameter is set too high, it will cause Full GC, or too low, it will cause frequent CMS GC. If this parameter is set too low, you should increase the size of the old GC.

2.6.3 CMS Failure Handling

There are two types of failures that can occur when running the CMS collector:

2.6.3.1 Concurrent Mode Failure

Concurrent mode failure occurs when the older generation cannot accommodate the objects promoted by the new generation GC, and concurrent mode failure means that the CMS degenerates into a Full STW GC, also known as Serial GC. Processing (actually it says above):

  1. Memory use CMS according to proportion to decide whether to start the CMS garbage collection, to down the ratio. – XX: XX: CMSInitiatingOccupancyFraction = N and – + UseCMSInitiatingOccupancyOnly. Setting both parameters allows the CMS to decide whether to start CMS garbage collection based solely on the usage ratio of older generations.
  2. More threads to run the CMS. The concurrent mode fails because the CMS can’t keep up with the speed of the objects in the old days. To set the number of background threads, set -xx :ConGCThreads=N. By default ConcGCThreads=(3+ParallelGCThreads)/4

2.6.3.2 Promoration Failure

There was enough space in the old age, but due to the serious fragmentation, it could not accommodate the object of promotion in the new generation, and promotion failure occurred.

Promotion failure is due to fragmentation, so the solution to this problem is how to reduce fragmentation. CMS provides two parameters to arrange pieces and compression: – XX: + UseCMSCompactAtFullCollection when this setting is used in FullGC sorts through debris and compression. – XX: CMSFullGCsBeforeCompaction = N how many times this parameter is set in the FullGC when the memory of the old s a defragmentation compression. By setting these two parameters, the fragmentation problem can be effectively optimized. It is also important to note that defragmenting and compressing fragments is a time-consuming operation, so be careful.

2.6.4 CMS Parameters

Based on the parameter configuration described above, the following are some parameters of the CMS:

-xx :+UseConcMarkSweepGC activates the CMS collector. The default is false

-xx :ConcGCThreads=N Sets the number of CMS threads

– XX: + UseCMSInitiatingOccupancyOnly only according to the old s use ratio to determine whether to CMS

– XX: CMSInitiatingOccupancyFraction set trigger a CMS recycling old s memory utilization ratio

-xx :+ CMSPARallelEnabled Run the final marking stage in parallel to speed up the final marking

Trigger – XX: + UseCMSCompactAtFullCollection CMS Full GC time finishing pieces at a time, false by default

– XX: CMSFullGCsBeforeCompaction = N after several Full GC finishing pieces at a time, when the default is 0, namely under the default configuration after each Full GC can do compression.

-xx :+CMSClassUnloadingEnabled Enables the CMS to collect persistent bands, which are not collected by default and will trigger a Full GC.

-xx :+CMSScavengeBeforeRemark forces a Minor GC before the final tag. Default is false.

2.7 G1 Collector

The G1 garbage collector is a new garbage collector that was officially introduced in JDK1.7. Oracle officially plans to make G1 the default garbage collector in JDK9, replacing CMS. The G1 features the following:

  1. As with the CMS collector, the GC operation executes concurrently with the application threads and is a multithreaded GC.
  2. The G1 collector can collect garbage from both young and old generations.
  3. The partition algorithm is used to cancel the traditional continuous generation mechanism of heap space, but the heap space is divided into a piece of small partition, but each partition is a generation.
  4. G1 is a collector based on the “mark-collation” algorithm as a whole, and on the local (between two regions) it is based on the “copy” algorithm. In the recycling process, an appropriate amount of objects will be moved, which effectively reduces memory fragmentation compared with CMS.
  5. Due to the small partition, some partitions are selected to recycle each GC, rather than the whole generation as before. In this way, the GC pause time can be more accurately controlled. In a small amount of time, the partitions with the most garbage can be collected first, and the low-pause garbage can be collected without sacrificing throughput.

G1 garbage collection algorithm is mainly applied to multi-CPU and large-memory services. While meeting the low pause time, it can improve the throughput as much as possible and deal with memory fragmentation at the same time.

2.7.1 Heap memory GC model for G1 collector

Previous garbage collectors such as CMS used the following heap memory GC model:

Young generation: Eden Space + 2 Survivor

Old space

Permanent generation: Perm space before 1.8

Metaspace: metaspace after 1.8

The characteristic of these memory Spaces is that they must be contiguous. G1 garbage collector compared with other collectors, the biggest difference is that it eliminates the physical division of young generation and old generation, and instead divides the heap into several regions. G1 does not require that the storage of objects must be physically continuous, as long as it is logically continuous. These regions contain logical young and old ages. An area could be Eden, Survivor, or Old. This way we no longer have to set up each generation in a separate space and worry about whether there is enough memory for each generation.

The size of a Region in the heap memory can be specified using the -xx :G1HeapRegionSize parameter. The Region size can be 1M, 2 m, 4M, 8M, 16M, or 32M. If G1HeapRegionSize is the default value, The practical size of Region is calculated during heap initialization as follows:

By default, 2048 pieces of heap memory are evenly divided to achieve a reasonable size.

Some of these areas contain the new generation, whose garbage collection still suspends all application threads, copying surviving objects to older generations or Survivor Spaces. The old era is also divided into regions, and the G1 collector cleans up by copying objects from one region to another. This means that, under normal processing, G1 compacts the heap (at least part of it) so that there is no CMS memory fragmentation problem.

The G1 collector has the following heap memory GC model:

Each Region is marked with E, S, O, and H, indicating that each Region plays a role at runtime. In G1, there is also a special Region called the Humongous Region, which represents regions that store large objects.

If an object occupies more than 50% of its partition capacity, the G1 collector considers it a giant object.

These giant objects, by default, are directly assigned to the old age, but if it is a short-lived giant object, it will have a negative impact on the garbage collector.

To solve this problem, G1 has a Humongous zone, which is dedicated to storing giant objects. If an H block does not fit a large object, G1 looks for contiguous H partitions to store it. Sometimes you have to start the Full GC in order to find consecutive H regions.

2.7.2 Working process of G1 collector

The G1 collector works in four stages: Young GC, concurrent mark cycle, Mixed GC, and Full GC.

2.7.2.1 Young GC

The Young GC mainly GC the Eden and Survivor zones and is triggered when the Eden zone runs out of space. Garbage collection in the younger generation is still done by suspending all application threads.

Data in Eden space is moved to Survivor space. If Survivor space is insufficient, some data in Eden space will be directly promoted to tenured space.

Survivor zone data is moved to the new Survivor zone, and some data is promoted to the old chronosphere.

Finally, data in Eden space is empty, data in Survivor area increases, data in Old area increases, GC stops working, and application thread continues to execute.

Yong GC before and after comparison:

The Young GC is also responsible for maintaining information such as the age of the object, the total number of times the live object has been collected by the Young generation. G1 maintains the sum of promoted objects’ sizes and their age information into the age table, Combine the age table, survivor ratio (-xx :TargetSurvivorRatio defaults to 50%), and maximum tenure threshold (-xx :MaxTenuringThreshold defaults to 15) to calculate an appropriate tenure threshold.

2.7.2.1.1 Remembered Set

When GC objects of the young generation, how do we find the root object of objects in the young generation? The root object can be in the young generation or in the old generation, so are all objects in the old generation roots?

It would take a lot of time to scan the entire age. So G1 introduced the concept of RSet. Its full name is Remembered Set and it keeps track of references to objects in a heap.

When each Region is initialized, an RSet is initialized, which records and traces references from other regions to objects in the Region. Each Region is divided into multiple cards with 512Kb by default. So what RSet needs to record is XX Card of XX Region.

2.7.2.2 Concurrent marking period

When the ratio of old ages reaches a certain parameter, G1 will first trigger the concurrent marking cycle, which is similar to CMS in that it is to reduce the pause time. After the concurrent marking, THE Mixed GC stage will be entered. The concurrency cycle is divided into six phases:

  1. Initial flag: Collect all GC Root objects, STW, and perform a Yong GC.
  2. Root region scan: After the Yong GC, Eden region is cleared. This phase scans older regions directly reachable from survivor regions and marks those directly reachable object references. This process can be performed concurrently with the application. However, the root region scan cannot be performed at the same time as the new generation GC (because the root region scan depends on the survivor region object, and the new generation GC will modify this region), so if the new generation GC needs to be performed at this time, the GC needs to wait until the root region scan is completed. If this happens, This Cenozoic GC will last longer.
  3. Concurrent marking: Marking live objects, which can be performed concurrently with the application and can be interrupted by a Yong GC.
  4. Re-marking: SWT, is the last marking phase and is very short. Because the application is still running during concurrent tagging, the tagging results may need to be corrected, so the last tagging results are supplemented here.
  5. Exclusive cleanup: SWT, which calculates and sorts the percentages of live objects and GC collections for each region, identifying regions available for mixed collection. At this stage, the RemeberedSet is also updated. This stage gives and marks the areas that need to be mixed for recycling. This information is needed in the mixed recycling stage.
  6. Cleanup phase: This is where completely idle areas are identified and cleaned up. It is concurrent elimination and does not cause pauses.

Comparison before and after the concurrent marking period:

  1. The Young block changes, which means that at least one YGC has occurred during G1 concurrency (unlike CMS), and Eden is completely cleared before the tag is marked because the application threads are working at the same time during the concurrency phase, so you can see that Eden is occupied again.
  2. Some areas are marked by G, but these areas still belong to O area, where data is still stored. The difference is that G1 has marked these areas as containing the most garbage, i.e. the areas with the highest recycling benefits.
  3. The O block actually becomes larger after the concurrency phase is complete (O+G blocks). This is because a new object enters the Yong GC during this process. In addition, this phase does not recycle any objects in the O region: its main purpose is to mark out the most garbage blocks. Objects actually start to be reclaimed later in the Mixed GC phase.

2.7.2.3 Mixed GC

Next, G1 performs a series of Mixed GCS, also known as hybrid GCS. This period is called the blending phase because Yong GC is performed simultaneously and the old age area marked G is cleaned up above. Here is a before and after schematic of the blending GC execution:

Mixed GC will continue multiple times until enough memory has been reclaimed, and the Mixed GC will end and then fire a separate Yong GC. Concurrency may or may not be marked thereafter depending on the age ratio.

When does the Mixed GC trigger? By the parameter – XX: InitiatingHeapOccupancyPercent = n. Default: 45%. This parameter is triggered when the age size as a percentage of the total heap size reaches this threshold.

We can set the MixedGC count, -xx :G1MixedGCCountTarget: The default value is 8, which means there is a physical limit on the number of Mixed collections that can be started. G1 is based on dividing the reclaimed old partition by this parameter to the minimum number of old years CSet worth collecting in each mixed collection.

-xx :G1HeapWastePercent: The default value is 5%. Each mix collection is paused and G1 calculates the waste percentage. Based on the waste percentage of the heap, no new mix collection is started when the collection reaches the parameter. When pause times and run times grow exponentially, you can use -xx :G1HeapWastePercent, which can help, but it also leads to more fragmentation.

2.7.2.4 Full GC

A Full GC is triggered if the allocation of large objects does not find contiguous enough partitions in the old age.

A Full GC will also be triggered if the object memory allocation rate is too fast, the mixed GC is out of space, or the Yong GC is too small for either S or O to hold the surviving object.

G1’s Full GC algorithm, like CMS’s, is single-threaded Serial GC, which results in long SWTS and requires constant tuning to avoid Full GC as much as possible.

2.7.3 Other parameters related to G1 collector

-xx :+UseG1GC: Enable the use of G1 garbage collector

-xx :MaxGCPauseMillis: Sets the maximum EXPECTED GC pause indicator. The default value is 200 milliseconds. If any pause exceeds this value, Gl will try to adjust the ratio of the new generation to the old generation, adjust the heap size, adjust the promotion age and other means to achieve the preset goal, but it is not guaranteed success. If the pause time is shortened, for the Cenozoic generation, this means that it is likely to increase the number of Cenozoic GCS, which in turn will become more frequent. For older regions, the number of regions collected at a time is also reduced in order to achieve shorter pause times when mixing GC collections, which definitely increases the likelihood of a Full GC.

-xx :G1HeapRegionSize=n: Size of the G1 region. The value is a power of 2 and ranges from 1 MB to 32 MB. The goal is to partition about 2048 regions based on the minimum Java heap size. The default is 1/2000 of the heap.

-xx :ParallelGCThreads=n: Sets the value of the number of STW worker threads. Sets the value of n to the number of logical processors. The value of n is the same as the number of logical processors, up to 8.

-xx :ConcGCThreads=n: Sets the number of parallel threads to be tagged. Set n to about 1/4 of the number of parallel garbage collection threads (ParallelGCThreads).

– XX: InitiatingHeapOccupancyPercent = n: set the trigger concurrent marking cycles of Java heap usage rate threshold value. The default value is 45, indicating that a concurrent marking cycle will be triggered when the usage is 45% of the entire Java heap. If InitiatingHeapOccupancyPercent value is big, can lead to concurrent cycle is slow to start, then cause the possibility of a Full GC also increase greatly, on the contrary, a too small InitiatingHeapOccupancyPercent value, Concurrency cycles are very frequent, and a large number of GC threads are preempting the CPU, causing application performance to degrade.

Related articles:

  1. In-depth Understanding of the Java Virtual Machine

If you need to communicate, or the article is wrong, please leave a message directly. In addition, I hope to like, collect, pay attention to, I will continue to update a variety of Java learning blog!