JVM system learning path series demo code address: github.com/mtcarpenter…
directory
- GC classification and performance indicators
- Overview of different garbage collectors
- Serial collector: Serial collector
- ParNew collector: Parallel collection
- Parallel collector: Throughput first
- CMS collector: Low latency
- G1 collector
- G1 collector: Regionalization generation type
- Garbage collector summary
GC classification and performance indicators
Garbage collectors are not specified in the specification and can be implemented by different vendors and versions of JVMS. Due to the rapid iteration of JDK versions, Java has spawned numerous GC versions to date. By analyzing the garbage collector from different perspectives, GC can be categorized into different types.
New features in different Java versions
- Syntax level: Lambda expression, switch, auto unboxing, enum
- API level: Stream API, new date and time, Optional, String, collection framework
- Low-level optimizations: JVM optimizations, GC changes, meta-space, static fields, string constant pool position changes
Garbage collector classification
Count by thread
The number of garbage collection threads can be divided into serial garbage collectors and parallel garbage collectors.
Serial collection means that only one CPU is allowed to perform garbage collection at a time, at which point the worker thread is suspended until the garbage collection is complete.
- In cases where hardware platforms are not particularly superior, such as single-CPU processors or small application memory, serial collectors can outperform parallel and concurrent collectors. So serial reclamation is applied by default to the JVM in Client mode on the Client side
- Parallel collectors produce shorter pause times than serial collectors on more concurrent cpus.
In contrast to serial collection, parallel collection can use multiple cpus to perform garbage collection at the same time, thus improving the throughput of the application, although parallel collection is still exclusive and uses a stop-the-world mechanism like serial collection.
According to the working mode
According to the working mode, can be divided into parallel garbage collector and exclusive garbage collector.
- And the garbage collector works alternately with application threads to minimize application pause time.
- Once run, the exclusive Stop the World garbage collector stops all user threads in the application until the garbage collection process is complete.
According to the fragmentation treatment
According to the way of debris treatment, it can be divided into compressed garbage collector and non-compressed garbage collector.
- The compressed garbage collector compresses the surviving objects after the collection is complete to eliminate the recovered fragments.
- Non-compressed garbage collectors do not do this.
According to the working memory interval
It can be divided into young generation garbage collector and old generation garbage collector.
Evaluate the performance metrics for GC
- throughput: The percentage of total run time spent running user code
- (Total run time = program run time + memory reclaim time)
- Garbage collection overhead: the complement of throughput, the ratio of the garbage collection time to the total elapsed time.
- Pause time: The amount of time a program’s worker thread is suspended while garbage collection is being performed.
- Collection frequency: How often collection operations occur relative to the execution of the application.
- Memory footprint: The amount of memory occupied by the Java heap.
- Fast: The time an object takes from birth to being recycled.
Throughput, pause times, and memory footprint all add up to an impossible triangle. The overall performance of all three will get better and better as technology advances. A good collector usually does at most two of these. Of these three, time out becomes increasingly important. Because more memory footprint becomes more tolerable as hardware evolves, hardware performance improvements also help reduce the impact of collector runtime on the application, which increases throughput. Memory expansion has a negative effect on latency. In brief, two main points should be taken:
- throughput
- The pause time
Throughput Is the ratio of the CPU time used to run user code to the total CPU consumption time, that is, throughput = user code running time/(user code running time + garbage collection time)
For example, if the virtual machine runs for 100 minutes and garbage collection takes 1 minute, the throughput is 99%.
In this case, applications can tolerate higher pause times, so high-throughput applications have a longer time baseline, and fast response is a throughput priority that doesn’t have to be considered, meaning that STW has the shortest time per unit of time: 0.2+0.2=0.4 Performance indicator: Pause Time“Pause time” refers to a period of time during which the application thread is suspended and the Gc thread is allowed to execute. For example, a 1ee millisecond pause time during Gc means that no application thread is active during that 1E0 millisecond period. Pause time priority means keeping the time of a single STW as short as possible: 0.1+0.1 +0.1 +0.1 =0.5 Throughput vs pause timeHigh throughput is good because it gives the end user of the application the impression that only application threads are doing “productive” work. Intuitively, the higher the throughput, the faster the application will run. Low pause times (low latency) are better because it is always bad from the end user’s point of view whether an application is suspended for GC or any other reason. Depending on the type of application, sometimes even a brief 200-millisecond pause can interrupt the end-user experience. Therefore, having low, large pause times is very important, especially for an interactive application. Unfortunately, “high throughput” and “low pause times” are competing goals. If you choose throughput first, you will necessarily need to reduce the frequency of memory collection, but this will result in the GC needing longer pause times to perform memory collection. On the contrary, if the principle of low latency first is selected, then in order to reduce the pause time of each memory reclamation, memory reclamation can only be performed frequently, but this causes the reduction of young generation memory and leads to the decrease of program throughput. When designing (or using) GC algorithms, we must determine our goals: a GC algorithm can only target one of two goals (i.e. focus only on large throughput or minimal pause times), or try to find a compromise between the two. Current standards:Reduce pause times when maximum throughput is first
Overview of different garbage collectors
Garbage collection is Java’s signature capability and greatly improves development efficiency. This is of course a hot topic for interviews. So, what are the common Java garbage collectors?
The GC garbage collector is a descendant of the JVM and is used in conjunction with the JVM, with different collectors for different usage scenarios
With virtual machines, there is a need to collect Garbage. This is Garbage Collection, and the corresponding product is called Garbage Collector.
- Along with JDK 1.3.1 in 1999 came SerialGc, the first GC in serial mode. The ParNew garbage collector is a multithreaded version of the Serial collector
- Parallel GC and Concurrent Mark Sweep GC were released along with JDK1.4.2 on February 26, 2002
- Parallel GC became the HotSpot default GC after JDK6.
- In 2012, G1 was available in JDK 1.7U4.
- In 2017, G1 became the default garbage collector in JDK9, replacing CMS.
- Parallel full garbage collection for G1 garbage collector in JDK10 in March 2018, implementing parallelism to improve worst-case latency.
- JDK11 was launched in September 2018. Introduced the Epsilon garbage collector, also known as the “no-OP” collector. At the same time, the introduction of ZGC: Scalable low-delay garbage Collector (Experimental)
- In March 2019, JDK12 was released. Enhanced G1 to automatically return unused heap memory to the operating system. Meanwhile, Shenandoah GC: Experimental GC with low pause time is introduced. · JDK13 was released in September 2019. Enhanced ZGC to automatically return unused heap memory to the operating system.
- In March 2020, JDK14 was released. Delete the CMS garbage collector. Extend ZGC on MacOS and Windows
Seven classic garbage collectors
- Serial collector: Serial, Serial old
- Parallel recyclers: ParNew, Parallel Avenge, Parallel old
- Concurrent collector: CMS, G11
The relationship between seven classic collectors and garbage generation
- Cenozoic collectors: Serial, ParNew, Paralle1 Scavenge;
- Collector: Serial old, Parallel old, CMS;
- Whole heap collector: G1;
The composition of the garbage collector
- There is a line between the two collectors, indicating that they can be used together: The Serial/Serial old, Serial/CMS, ParNew/Serial old, ParNew/CMS, Parallel Scavenge/Serial 0ld, Parallel Scavenge/Parallel insane 0 ld, G1;
- Serial Old is the backup plan for Concurrent Mode Failure of CMS.
- (red dotted line) Due to maintenance and compatibility testing costs, the combination Serial+CMS and ParNew+Serial Old was declared deprecated in JDK 8 (JEP173) and completely unsupported in JDK9 (JEP214), i.e., removed.
- Insane and Serialold GC. (green dashed line) JEP366
- In JDK14: Delete CMS garbage collector (JEP363)
Why have a lot of collectors? Is one not enough? Because Java is used in many scenarios, mobile, server and so on. Therefore, it is necessary to provide different garbage collectors for different scenarios to improve the performance of garbage collection. Although we will compare each collector, we are not trying to pick the best one. There is no one-size-fits-all, one-size-fits-all collector, and there is no one-size-fits-all collector. So we chose only the collector that was most appropriate for our specific application.
How to view the default garbage collector -xx :+PrintcommandLineFlags: View command line related parameters (including the garbage collector used) using the command line command: jinfo-flag Related garbage collector parameters process ID
Serial collector: Serial collector
- The Serial collector is the most basic and oldest garbage collector. The only option to recycle the new generation before JDK1.3.
- The Serial collector is the default new generation garbage collector in Client mode in HotSpot.
- The Serial collector performs memory collection using a copy algorithm, Serial collection, and a “stop-the-world” mechanism.
- In addition to the young generation, the Serial collector also provides the Serial Old collector for performing the old generation garbage collection. The Serial Old collector also uses Serial collection and “stop the World” mechanisms, but the memory collection algorithm uses a mark-compression algorithm.
- Serial Old is the default old garbage collector running in Client mode
- Serial Old has two main uses in Server mode:
- To be used in conjunction with the New Generation of the Parallel Insane
- As a back-up garbage collection solution for older CMS collectors
The collector is a single-threaded collector, but its “single-threaded” meaning does not merely mean that it uses only one CPU or one collection thread to complete garbage collection. More importantly, it must suspend all other worker threads while it is garbage collection until it stops The World.
- Advantages: Simple and efficient (compared to the single-threaded collections of other collectors), Serial collectors can achieve maximum single-threaded collection efficiency in a single-CPU-limited environment because they have no overhead of thread interaction.
- A virtual machine running in client mode is a good choice.
- In a user’s desktop application scenario, the available memory is generally small (tens of MB to one or two hundred MB), garbage collection can be completed in a relatively short time (tens of ms to more than one hundred ms), and serial collector is acceptable as long as it does not occur frequently.
- In the HotSpot VIRTUAL machine, use
- XX: + UseSerialGC
Parameter can specify that both young and old generations use the serial collector.- This is equivalent to replacing Serial GC for freshmen and Serial old GC for seniors
To summarize this garbage collector as you know, serial is no longer used. And in the limited single-core CPU can only be used. It’s not even mono anymore. For highly interactive applications, this garbage collector is unacceptable. Serial garbage collectors are not typically used in Java Web applications.
ParNew collector: Parallel collection
- If the Serial GC is a single-threaded garbage collector in the younger generation, the ParNew collector is a multithreaded version of the Serial collector.
- Par is short for Parallel, New: only deals with the New generation
- There is little difference between the two garbage collectors except that the ParNew collector performs memory collection in a parallel collection manner. The ParNew collector also uses a copy algorithm, a “stop-the-world” mechanism, in the younger generation.
- ParNew is the default garbage collector for the new generation of many JVMS running in Server mode.
- For the new generation, the recycling times are frequent and the parallel method is efficient.
- For the old age, the number of recycling is less, using the serial way to save resources. (CPU parallel need to switch threads, serial can save the resources of switching threads)
- Since the ParNew collector is based on parallel collection, is it safe to assume that the ParNew collector will be more efficient at collecting than the Serial collector in any scenario?
- The ParNew collector runs in a multi-CPU environment. Because it can make full use of physical hardware advantages such as multi-CPU and multi-core, it can complete garbage collection more quickly and improve the throughput of the program.
- But the ParNew collector is not as efficient as the Serial collector in a single CPU environment. Although the Serial collector is based on Serial collection, because the CPU does not need to switch tasks frequently, it can effectively avoid some of the extra overhead associated with multithreaded interactions.
- Because in addition to Serial, only the ParNew GC currently works with the CMS collector
In the program, the developer can manually specify the use of the ParNew collector to perform memory reclamation tasks with the option “-xx: +UseParNewGC”. It means that the younger generation uses the parallel collector without affecting the older generation. -xx :ParallelGCThreads Limits the number of threads that are enabled by default.
Parallel collector: Throughput first
- The younger generation of HotSpot, in addition to having the ParNew collector based on Parallel recycling, also uses copying algorithms, Parallel recycling, and “Stop the World” mechanisms.
- So is Parallel collector superfluous?
- Unlike the ParNew collector, the ParallelScavenge collector aims to achieve a manageable Throughput. It is also known as a throughput-first garbage collector.
- The adaptive adjustment strategy is also an important distinction between the Parallel Avenge and ParNew.
- High throughput can efficiently use THE CPU time, as soon as possible to complete the operation of the program, mainly suitable for the background operation without too much interaction. Therefore, it is commonly used in server environments. For example, applications that perform batch processing, order processing, payroll, and scientific calculations.
- Parallel collector a Parallel old collector for performing old-age garbage collection was provided in JDK1.6 in place of the old-age serialold collector.
- The Parallel old collector uses a mark-compression algorithm, but is also based on Parallel collection and a stop-the-world mechanism.
In application throughput first scenarios, the combination of Parallel collector and Parallel Old collector performs well in server mode memory reclamation. In Java8, the default is this garbage collector.Parameter configuration
- XX: + UseParallelGC
Manually specify the young generation to perform memory reclamation tasks using the Parallel collector.- XX: + UseParalleloldcc
Manually specifying older generations is done using a parallel collection collector.- It applies to the new generation and the old age respectively. Jdk8 is enabled by default.
- One of the above two parameters is enabled by default, and the other is enabled as well. (Mutual activation)
-XX:ParallelGcrhreads
Sets the number of threads for the young generation parallel collector. In general, it is best to match the number of cpus to avoid too many threads affecting garbage collection performance.- By default, when the number of cpus is less than eight, ParallelGcThreads is equal to the number of cpus.
- ParallelGCThreads = 3+[5*CPU Count]/8 when the number of cpus is greater than 8
-XX:MaxGCPauseMillis
Set the maximum garbage collector pause time (that is, the time of STW). The units are milliseconds.- To keep the pause time within MaxGCPauseMills as much as possible, the collector adjusts the Java heap size or some other parameter as it works.
- For users, the shorter the pause, the better the experience. But on the server side, we focus on high concurrency, overall throughput. So the server side is suitable for Parallel control.
- Use this parameter with caution.
-XX:GCTimeRatio
Ratio of garbage collection time to total time (=1/ (N+1)). Used to measure throughput size.- The value ranges from 0 to 100. The default value is 99, which means the garbage collection time is less than 1.
- With the former one
-XX:MaxGCPauseMillis
Parameters are somewhat contradictory. The longer the pause time, the Radio parameters tend to exceed the set ratio.
-XX:+UseAdaptivesizepplicy
Set up a Parallel Scavenge collector with an adaptive adjustment strategy- In this mode, parameters such as the size of the young generation, the ratio of Eden to Survivor, and the age of objects promoted to the old generation are adjusted automatically to reach a balance between heap size, throughput, and pause time.
- In cases where manual tuning is difficult, you can use this adaptive approach to specify only the maximum heap of the virtual machine, the throughput of the target (GCTimeRatio), and the pause time (MaxGCPauseMills), and let the virtual machine do the tuning itself.
CMS collector: Low latency
- In the JDK1.5 era, Hotspot introduced a garbage collector that could almost be considered revolutionary in strongly interactive applications: CMS (Concurrent-mark-sweep) collector, the first truly Concurrent collector in the HotSpot VIRTUAL machine, enables the garbage collector thread to work simultaneously with the user thread for the first time.
- The FOCUS of the CMS collector is to minimize the pause time of user threads during garbage collection. The shorter the pause times (low latency), the better the application that interacts with the user, and the better the response speed improves the user experience.
- 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.
- CMS’s garbage collection algorithm uses mark-sweep and also “stop-the-world”
- Unfortunately, CMS as an older collector does not work with the Parallel insane, a new generation collector that already exists in JDK1.4.0, so when CMS is used to collect older ages in JDK1.5, The new generation can only choose one of the ParNew or Serial collectors.
- Before G1, CMS was widely used. Today, there are still many systems using CMS GC.
The whole process of CMS is more complex than the previous collector. The whole process is divided into four main stages, namely the initial marking stage, concurrent marking stage, re-marking stage and concurrent clearing stage. (The main stages involved in STW are: initial marking and re-marking)
- Initial-mark phase: In this phase, all worker threads in the program are briefly paused due to stop-the-world, and the primary task of this phase is simply to Mark objects that GCRoots can be directly associated with. Once the tag completes, all application threads that were suspended will be resumed. Because the directly related object is small, the speed here is very fast.
- Concurrent-mark phase: The process of traversing the entire object graph from the directly associated objects of GC Roots. This process is time-consuming but does not require the suspension of the user thread and can be run concurrently with the garbage collection thread.
- Re-marking phase: Because in concurrent mark phase, the program will work thread and garbage collection threads run at the same time or cross operation, thus to correct during concurrent tags, tags that changes caused by the user program continue to operate the part of object mark record, this phase of the pause time usually slightly longer than the initial mark phase, but also far shorter than the concurrent mark phase.
- Concurrent-sweep phase: This phase removes dead objects judged by the concurrent-sweep phase, freeing up memory. Since there is no need to move live objects, this phase can also be concurrent with the user thread.
Although the CMS collector uses concurrent collection (non-exclusive), it still performs a stop-the-world mechanism to suspend the worker threads in the program during its initialization and re-marking phases, but not for very long. Thus, none of the current garbage collectors do not need stop-the-world at all, but only pause times as short as possible. Because the most time-consuming concurrent marking and concurrent cleanup phases do not require pauses, the overall collection is low-pause. In addition, since the user threads are not interrupted during the garbage collection phase, you should also ensure that the application user threads have enough memory available during the CMS collection process. Therefore, the CMS collector does not wait until the old age is almost completely filled, as other collectors do. Instead, the CMS collector starts collecting when the heap memory usage reaches a certain threshold to ensure that the application still has enough space to run while the CMS is working. If the CMS is running without enough memory to meet the program’s requirements, a “Concurrent Mode Failure” occurs, at which point the virtual machine starts a fallback: the Serial old collector is temporarily enabled to restart the old garbage collection, resulting in long pauses. The CMS collector adopts the garbage collection algorithmMark clearing algorithm, which means that after each memory reclamation, some memory fragmentation will inevitably occur because the memory space occupied by the useless objects that perform the memory reclamation is most likely to be discrete chunks. The CMS will not be able to use the Bump the Pointer technique to allocate memory for new objects, and will only be able to select the Free List to allocate memory.
Why doesn’t CMS use a mark-up algorithm?
The answer is simple, because when concurrent cleanup is done, using Compact memory, how do you use the memory used by the user thread? To ensure that the user thread can continue to execute, the resource it is running on is not affected. The Mark Compact is better suited for “Stop the world” scenarios.
- advantages
- Concurrent collection
- Low latency
- disadvantages
- Memory fragmentation occurs, resulting in insufficient space for user threads after concurrent cleanup. In the case that large objects cannot be allocated, the Full GC has to be triggered early.
- The CMS collector is very sensitive to CPU resources. In the concurrent phase, it does not cause user pauses, but it does slow down the application and reduce overall throughput by taking up a portion of the threads.
- The CMS collector cannot handle floating garbage. A “Concurrent Mode Failure” may occur, resulting in another Full GC. In the concurrent marking stage, the worker thread and garbage collection thread of the program run at the same time or cross, so if new garbage objects are generated in the concurrent marking stage, CMS will not be able to mark these garbage objects, which will eventually lead to the timely collection of these newly generated garbage objects. These previously unreclaimed memory Spaces can only be freed on the next GC.
Set the parameter **
- XX: + UseConcMarkSweepGC
Manually specify the use of the CMS collector to perform memory reclamation tasks.- If this parameter is enabled, it is automatically enabled
- xx: + UseParNewGC
To open. ParNew (Young) +CMS (OLd) +Serial OLd.
- If this parameter is enabled, it is automatically enabled
-XX:CMSInitiatingoccupanyFraction
Set a threshold for heap memory usage, and once this threshold is reached, collection begins.- The default value for JDK5 and previous versions is 68, which means that a CMS collection is performed when the space usage of the older generation reaches 68%. The default value for JDK6 or later is 92%
- If memory growth is slow, you can set a slightly larger value. A larger threshold can effectively reduce the trigger frequency of the CMS, and reducing the number of recycle times can significantly improve application performance. Conversely, if your application’s memory usage is growing rapidly, you should lower this threshold to avoid triggering the old serial collector too often. Therefore, this option can effectively reduce the number of Full GC executions.
- XX: + UseCMSCompactAtFullCollection
Used to specify when Full is finished- After GC, the memory space is compressed to avoid memory fragmentation. The problem, however, is that the pause times become longer because the memory compacting process cannot be executed concurrently.
-XX:CMSFullGCsBeforecompaction
Sets the number of Full GC runs after the memory space is compressed.-XX:ParallelcMSThreads
Set the number of threads in the CMS.- ParallelGCThreads (ParallelGCThreads +3) /4 is the default number of threads started by CMS. ParallelGCThreads is the number of threads started by the younger generation of Parallel collectors. When CPU resources are tight, application performance can be very poor during the garbage collection phase due to the impact of CMS collector threads.
summary
HotSpot has so many garbage collectors, so if someone asks, what is the difference between Serial GC, Parallel GC, and Concurrent Mark Sweep GC? Please remember the following passwords:
- If you want to minimize memory and parallel overhead, choose Serial GC;
- If you want to maximize the throughput of your application, Parallel GC;
- If you want to minimize GC interrupts or pauses, select CMS GC.
Changes to CMS in later JDK releases
- JDK9 new features: CMS is marked as Eprecate (JEP291)
- If parameters are used for the HotSpot VIRTUAL machine of JDK9 and later
- XX: + UseConcMarkSweepGC
To enable the CMS collector, the user will receive a warning that the CMS will be deprecated in the future.
- If parameters are used for the HotSpot VIRTUAL machine of JDK9 and later
- New features for JDK14: Remove CMS garbage collector (JEP363)
- Remove the CMS garbage collector if used in JDK14
- XX: + UseConcMarkSweepGC
The JVM does not return an error, just a warning message, but no exit. The JVM automatically falls back and starts the JVM in the default GC mode.
- Remove the CMS garbage collector if used in JDK14
G1 collector
Why release Garbage First (G1) when we already have the First few powerful GCS? The reason is that applications are dealing with more and more large and complex businesses, more and more users, without GC can not ensure the normal operation of the application, and often the STW GC can not keep up with the actual needs, so they constantly try to optimize GC. The G1 (garbage-first) Garbage collector is a new Garbage collector introduced after Java7 update4, and is one of the most advanced achievements in today’s collector technology development. At the same time, in order to accommodate today’s expanding memory and increasing number of processors, pause time is further reduced while maintaining good throughput. The official goal for the G1 is to achieve the highest throughput possible with manageable latency, hence the heavy burden and expectation of a “fully functional collector.”
Why is it called Garbage First(G1)?
- Because G1 is a parallel collector, it divides heap memory into a number of unrelated regions (physically discontinuous). Use different regions to represent Eden, Survivor 0, Survivor 1, old age, and so on.
- The G1 GC systematically avoids region-wide garbage collection across the entire Java heap. G1 tracks the value of garbage accumulation in each Region (the amount of garbage collection space obtained and the experience value of garbage collection time), maintains a priority list in the background, and collects garbage from the Region with the highest value according to the allowed collection time.
- Since this approach focuses on regions where the most Garbage is collected, we gave G1 a name: Garbage First.
- Gbage-first (G1) is a Garbage collector for server applications. It is mainly aimed at machines equipped with multi-core CPUS and large memory capacity. It can meet the GC pause time with a high probability and has high throughput.
- In JDK1.7, it has removed the identifier of Experimenta1 and is the default garbage collector after JDK9, replacing CMS collector and the Parallel+Parallel old combination. Oracle officially calls it a “full-featured garbage collector.”
- Meanwhile, CMS has been marked as deprecated in JDK9. Is not the default garbage collector in JDK8 and needs to be used
- XX: + UseG1GC
To enable.
Advantages of the G1 garbage collector
Compared to other GC collectors, G1 uses an entirely new partitioning algorithm, characterized as follows: parallelism and concurrency
- Parallelism: G1 can have multiple GC threads working at the same time during collection, effectively leveraging multi-core computing power. At this point the user thread is STW
- Concurrency: G1 has the ability to alternate execution with the application, so that some work can be performed at the same time as the application, so that, generally speaking, the application does not completely block during the entire reclamation phase
Generational collection
- In terms of generation, G1 is still a generational garbage collector. It differentiates the young generation from the old generation, and the young generation still has Eden and Survivor zones. However, from the structure of the heap, it does not require the whole Eden area, the young generation or the old generation to be continuous, nor does it insist on fixed size and fixed quantity.
- The heap space is divided into regions that contain logical young and old generations.
- Unlike previous recyclers, it takes care of both the young and the old. Compare other recyclers, either working in the younger generation or working in the older generation;
That’s not what G1 calls generational It’s a region that looks like this Spatial integration
- CMS: “mark-clean” algorithm, memory fragmentation, defragmentation after several GC
- The G1 divides memory into regions. Memory reclamation is based on region. Region to Region is a copy algorithm, but overall can actually be regarded as a mark-compact algorithm, both algorithms can avoid memory fragmentation. This feature helps programs run for a long time and allocate large objects without triggering the next GC prematurely because contiguity memory space cannot be found. This is especially true when the Java heap is very large.
Predictable pause time model (i.e. This is another advantage G1 has over CMS. In addition to pursuing low pauses, G1 can also build a predictable pause time model, allowing users to explicitly specify that no more than N milliseconds should be spent on garbage collection within a time segment of M milliseconds.
- Due to partitioning, G1 can select only part of the region for memory reclamation, which reduces the scope of reclamation, so that the occurrence of global pause can be well controlled.
- G1 tracks the value of garbage accumulation in each Region (the amount of garbage collection space obtained and the experience value of garbage collection time), maintains a priority list in the background, and collects garbage from the Region with the highest value according to the allowed collection time. The G1 collector is guaranteed to achieve the highest possible collection efficiency in a limited time.
- G1 is not necessarily as good at delaying pauses as CMS GC is at best, but much better at worst.
Disadvantages of the G1 garbage collector
Compared to CMS, G1 does not have a comprehensive, overwhelming advantage. For example, G1 has a higher garbage collection Footprint and overload than CMS during user program execution. Empirically, CMS is more likely to outperform G1 in small memory applications, while G1 is more likely to outperform G1 in large memory applications. The balance point is between 6-8GB.
G1 Parameter Settings
-XX:+UseG1GC
: Manually specifies the use of the G1 garbage collector to perform memory reclamation tasks-XX:G1HeapRegionSize
Set the size of each Region. The value is a power of 2, ranging from 1 MB to 32 MB, and the goal is to partition about 2048 regions based on the minimum Java heap size. The default is 1/2000 of the heap.-XX:MaxGCPauseMillis
: Sets the desired maximum Gc pause time metric (which the JVM tries to achieve, but is not guaranteed to achieve). The default value is 200ms.-XX:+ParallelGcThread
Sets the value of the number of STW worker threads. The maximum value is 8.-XX:ConcGCThreads
Sets the number of threads to mark concurrently. Set n to about 1/4 of the number of parallel garbage collection threads (ParallelGcThreads).-XX:InitiatingHeapoccupancyPercent
Sets the Java heap usage threshold that triggers concurrent Gc cycles. If this value is exceeded, GC is triggered. The default value is 45.
Common steps for the G1 collector
G1 was designed to simplify JVM performance tuning by developers in three simple steps:
- Step 1: Start the G1 garbage collector
- Step 2: Set the maximum memory for the heap
- Step 3: Set a maximum pause time
There are three garbage collection modes available in G1: YoungGC, Mixed GC, and Full GC, which are triggered under different conditions.
Application scenarios for the G1 collector
- Server – oriented applications for machines with large memory and multiple processors. (No surprise in a normal size heap)
- The most important applications are applications that require low GC latency and have a large heap of solutions;
- For example, when the heap size is about 6GB or larger, predictable pause times can be less than 0.5 seconds; G1 ensures that each GC pause is not too long by incrementally cleaning only some regions at a time, not all of them. To replace the CMS collector in JDK1.5; Using 61 May be better than CMS in the following cases:
- More than 50% of the Java heap is occupied by active data;
- The frequency of object assignment or chronological lifting varies greatly;
- GC pauses are too long (longer than 0.5 to 1 second)
- While HotSpot garbage collectors use built-in JVM threads to perform multithreaded GC operations, G1 garbage collectors can use application threads to perform background GC operations when the JVM’s GC thread is slow. Application threads are called to help speed up the garbage collection process.
Partition Region: Divide the whole into parts
Using the G1 collector, it divides the entire Java heap into approximately 2048 independent Region blocks of the same size, each Region block size depending on the actual size of the heap, and the overall Region block size is controlled between 1MB and 32MB, and is the NTH power of 2, i.e. 1MB, 2MB, 4MB, 8MB, 16MB, 32MB. Can be achieved by-XX:G1HeapRegionsize
Setting. All regions are the same size and do not change during the lifetime of the JVM. Although the concept of Cenozoic and oldyn is still retained, Cenozoic and oldyn are no longer physically separated; they are collections of parts of regions (which do not need to be continuous). Dynamic Region allocation is used to achieve logical continuity.
- A region may belong to an Eden, Survivor, or old/Tenured memory region. However, a region can belong to only one role. In the figure, E indicates that the region belongs to Eden memory region, S indicates that the region belongs to survivor memory region, and O indicates that the region belongs to old memory region. Blank Spaces in the figure represent unused memory space.
- The G1 garbage collector also adds a new memory region called the Humongous memory region, shown in block H. It is used to store large objects. If the number of regions exceeds 1.5, it is placed in H.
The reason for setting H: Objects in the heap are directly assigned to the old age by default, but if it is a large object with a short life it will have a negative impact on the garbage collector. To solve this problem, G1 has a Humongous section, which is dedicated to large objects. If an H block does not fit a large object, G1 looks for contiguous H blocks to store. Sometimes you have to start the Full Gc in order to find consecutive H regions. Most of G1’s behavior treats the H region as part of the old age. Each Region allocates space via pointer collisions
The G1 garbage collector collection processThe garbage recovery process of G1GC mainly includes the following three links:
- Young GC
- Concurrent Marking in the old days
- Mixed GC
(Single-threaded, exclusive, high-intensity FullGC will continue to exist if needed. It provides a fail-safe mechanism against GC evaluation failures, i.e., strong collection.
Clockwise, young GC -> Young GC + Concurrent mark->Mixed GC order. The application allocates memory and starts the young generation reclamation process when the young generation’s Eden area is exhausted. G1’s young-generation collection phase is a parallel, exclusive collector. During the young generation collection period, G1GC suspends all application threads and starts multithreading to perform the young generation collection. Then move the surviving object from the young generation to the Survivor or the old, or possibly both. When heap memory usage reaches a certain value (45% by default), the old-age concurrent marking process begins. Mark completion to begin the mixed recycling process immediately. For a mixed payback period, G1GC moves live objects from the old period to the free period, which becomes part of the old period. Unlike the young generation, the G1 collector of the old generation does not need to recycle the entire old generation, but only scan/reclaim a small number of old regions at a time. At the same time, the old Region is reclaimed along with the young generation. For example, a Web server with a Java process with a maximum heap memory of 4 gigabytes responds to 1500 requests per minute and allocates about 2 gigabytes of new memory every 45 seconds. G1 does a young generation collection every 45 seconds, with a heap utilization rate of 45% every 31 hours, and begins the old generation concurrent tagging process, followed by four or five mixed collections.Remembered Set
- The problem of an object being referenced by different regions
- A Region cannot be isolated. Objects in a Region can be referenced by objects in any Region. Do YOU need to scan the entire Java heap to determine whether an object is alive?
- This problem also exists in other generational collectors (more so in G1)
- Will the new generation also have to scan the old?
- This would reduce MinorGC’s efficiency;
Solutions:
- For both G1 and other generational collectors, the JVM uses Remembered Set to avoid global scans:
- Each Region has a Remembered Set.
- Each time a Reference data Write operation is performed, a Write Barrier operation is generated.
- Then check whether the Reference to be written refers to an object in a different Region from the Reference type data (other collectors: check whether old objects refer to new ones).
- If not, the related references are recorded in the Remembered Set of the Region where the reference points to the object through cardTable.
- When garbage collection is performed, add the enumeration scope of the GC root to Remembered Set. You can guarantee that no global scan will be done, and there will be no omissions.
G1 recovery process – Young generation GC
When JVM starts, G1 prepares Eden area first, and the program continuously creates objects to Eden area during the running process. When Eden space runs out, G1 will start a young generation garbage collection process. In YGC, G1 first stops The application’s execution (stop-the-world) and G1 creates a Collection Set, which is a Collection of memory segments that need to be reclaimed. The return collection of the young generation collection process contains all memory segments in the Eden and Survivor regions of the young generation.Then start the following recycling process:
- In the first stage, the roots are scanned
The root refers to the object to which the static variable points, the local variable in the chain of method calls being executed, and so on. The root reference, along with the external reference to the RSet record, serves as the entry point for scanning the living object.
- Phase 2, update the RSet
Process cards in the Dirty Card queue (see remarks) and update the RSet. After this phase is complete, the RSet can accurately reflect the reference of the old age to the object in the memory segment.
- In the third stage, the RSet is processed
Identify the objects in Eden that are pointed to by the old objects. The objects in Eden that are pointed to are considered alive.
- In the fourth stage, objects are copied.
At this stage, the object tree is traversed, and the surviving objects in the memory segment of Eden area will be copied to the hollow memory segment of Survivor area. If the age of surviving objects in the memory segment of Survivor area does not reach the threshold, the age will be increased by 1. When the age reaches the threshold, the surviving objects will be copied to the hollow memory segment of old area. If Survivor space is insufficient, some data in Eden space will be promoted directly to the old space.
- The fifth stage deals with references
Handle Soft, Weak, Phantom, Final, JNI Weak etc references. Finally, the data in Eden space is empty, GC stops working, and the objects in the target memory are continuously stored without fragmentation. Therefore, the replication process can achieve the effect of memory consolidation and reduce fragmentation.
G1 recycling process – Concurrent marking process
- Initial marking phase: marking objects directly reachable from the root node. This phase is STW and triggers a young GC.
- Root Region Scanning: THE G1 GC scans the old Region objects that are directly reachable from the Survivor Region and marks the referenced objects. This process must be completed before the Young GC.
- Concurrent Marking: Concurrent Marking (and application execution) throughout the heap, which may be interrupted by youngGC. During the concurrent marking phase, if all objects in a region object are found to be garbage, the region is immediately reclaimed. At the same time, the object activity (the percentage of living objects in the region) of each region is calculated during concurrent tagging.
- Remark: Because the application is ongoing, the result of the last mark needs to be corrected. Is the STW. G1 uses a faster initial snapshot algorithm than CMS: snapshot-at-the-beginning (SATB).
- Exclusive cleanup (STW) : Calculates the percentage of live objects and GC collections for each region and sorts them to identify areas that can be mixed for collection. Set the stage for the next phase. Is the STW. This phase does not actually do garbage collection
- Concurrent cleanup phase: Identify and clean up completely free areas.
G1 Recovery process – Mixed recovery
As more and more objects are promoted to old regions, to avoid running out of heap memory, the virtual machine fires a Mixed garbage collector, called Mixed GC. This algorithm is not an old GC, but instead reclaims the entire Young region. Some old regions will also be reclaimed. Note here:Some of the old, not all of the old. You can select which old regions to collect, thus controlling the garbage collection time. Also note that Mixed GC is not a Full GC.
- After the concurrent marking ends, the segments that are 100% garbage in the old age are reclaimed and the segments that are partially garbage are calculated. By default, these older memory segments are divided eight times
-XX:G1MixedGCCountTarget
Set) is reclaimed - The Collection Set of a mixed Collection consists of one-eighth of old age segments, Eden segment, and Survivor segment. The algorithm of hybrid collection is exactly the same as the algorithm of young generation collection, but it collects more memory segments of the old generation. Please refer to the young generation recycling process above for details.
- Since memory segments are recycled eight times by default in older generations, G1 prioritises memory segments with more garbage. The higher the percentage of garbage in memory segments, the more garbage will be collected first. And there is a threshold that determines whether memory segments are reclaimed,
-XX:G1MixedGCLiveThresholdPercent
, the default is 65%, meaning that garbage must be 65% of the memory segment before it is collected. If the garbage ratio is too low, it means that there is a high percentage of live objects, which will take more time to replicate.- Mixed recycling does not have to be done eight times. There is a threshold
-XX:G1HeapWastePercent
, the default value is 10%, meaning that 10% of the total heap memory is allowed to be wasted, meaning that if the percentage of garbage that can be collected is less than 10% of the heap memory, no mixed collection is performed. Because GC takes a lot of time but recycles very little memory.
G1 Collection optional process – Full GC
- The G1 was designed to avoid Full GC. But if that doesn’t work, G1 stops The application’s execution (stop-the-world) and uses a single-threaded memory reclamation algorithm for garbage collection, with poor performance and long application pauses.
- To avoid Full GC, you need to adjust once it happens. When will Full GC happen? For example, if the heap is too small, G1 will fall back to full GC when there is no empty segment available for copying live objects, a situation that can be resolved by increasing memory. There are two possible reasons for G1 Full GC:
- Evacuation without sufficient to-space to hold objects of advancement;
- Space runs out before the concurrent processing completes.
Optimization suggestions for G1 recovery
According to official information from Oracle, the Evacuation phase was designed to be executed concurrently with user programs, but this is complicated and is not urgent considering that G1 only returns to part of a Region and the pause times are controlled by the user. Instead, we chose to put this feature into the low-latency garbage collector (ZGC) that emerged after G1. In addition, considering that G1 is not only geared toward low latency, pausing the user thread can maximize garbage collection efficiency, so the implementation of pausing the user thread completely was chosen to ensure throughput.
-
Young generation size
- Avoid the use of
-Xmn
或-XX:NewRatio
And other related options explicitly set the young generation size - Fixed the size of the young generation to be overridden
- Avoid the use of
-
Pause time Goals Don’t be too strict with your pause time goals
- The throughput goal for the G1 GC is 90% application time and 10% garbage collection time
- When evaluating the throughput of G1GC, don’t be too harsh with pause time goals. Being too stringent means you are willing to incur more garbage collection overhead, which directly affects throughput.
Garbage collector summary
As of JDK1.8, there are seven different garbage collectors. Each garbage collector has different characteristics, in the specific use of time, need to choose different garbage collectors according to the specific situation. Serial=> Parallel => CMS => G1 => ZGC
Garbage collector combinationVm implementations of different vendors and versions vary greatly. The HotSpot VIRTUAL machine after JDK7/8 all collectors and their combinations are shown below How do I choose a garbage collector
- The configuration of the Java garbage collector is an important choice for JVM optimization, and choosing the right garbage collector can make a big difference in JVM performance.
- How do I choose a garbage collector?
- Prioritizing the heap size allows the JVM to adapt.
- If memory is less than 100M, use a serial collector
- If it is a single-core, single-machine program, and no pause time requirements, serial collector
- If it is multi-CPU, requires high throughput, and allows pause times of more than 1 second, choose parallelism or the JVM’s choice
- If you have multiple cpus and are looking for low pause times that require fast responses (such as a delay of no more than 1 second, as in Internet applications), use a concurrent collector
- The G1 is officially recommended for high performance. The current Internet projects are basically using G1.
- Finally, one point needs to be clarified:
- There is no single best collector, and there is no universal collector
- Tuning is always for specific scenarios, specific needs, and there is no one-size-fits-all collector
G1 collector: Regionalization generation type
By reading GC logs, we can understand the Java virtual machine memory allocation and reclamation policies. List of parameters for memory allocation and garbage collection
-XX:+PrintGc
Output GC logs. Similar: verbose: gc-XX:+PrintGcDetails
Prints verbose logs for Gc-XX:+PrintGcTimestamps
Output Gc timestamp (in base time)-XX:+PrintGCDatestamps
Output the Gc timestamp (in the form of a date, for example 2013-05-04T21:53:59.234 +0800)-XX:+PrintHeapAtGC
The heap information is printed before and after Gc-Xloggc:.. /logs/gc.1og
Output path of log files
verbose:gcTo open the GC log:-verbose:gc
This only shows the total GC heap change as follows:Argument parsing PrintGCDetailsTo open the GC log:-verbose:gc -XX:+PrintGCDetails
Enter the following informationArgument parsing supplement
-
[GC” and “[Full GC” indicate The type of pause for The garbage collection, with “Full” indicating that The GC has “stopped The World”
-
Using Serial collector the name of the New Generation is Default New Generation, so “[DefNew” is displayed.
-
– The name of the collector using ParNew in the New Generation will change to “ParNew”, which means “Parallel New Generation”
-
Use the Parallel Scavenge collector. The Cenozoic insane is called “PSYoungGen”.
-
The name of the old collection is determined by the collector, just like the new one
-
Using the G1 collector, it shows “garbage-first heap”
Allocation Failure indicates that this time GC is caused because there is not enough space in the young generation to store new data.[PSYoungGen: 5986K->696K]5986K->704K (9216K)
Outside the brackets: size of the young generation and the old generation before GC collection, size of the old generation after GC collection, (total size of the young generation and the old generation) User represents the user-mode recycling time, sys kernel-mode recycling time, and rea actual recycling time. Due to multicore, the total time may exceed reA1 time
Young GC pictures FullGC pictures Example of GC collection We write a program to illustrate the process of GC collection
/** * -xx :+ printCommandFlags ** -xx :+UseSerialGC: indicates that the new generation uses the Serial Old GC ** -xx :+UseParNewGC: ParNew GC * * -xx :+UseParallelGC * -xx :+UseParallelOldGC: * * -xx :+UseConcMarkSweepGC: UseConcMarkSweepGC: UseConcMarkSweepGC Also, the young generation triggers the use of ParNew *@author shkstart [email protected]
* @create2020 0:10 * /
public class GCUseTest {
public static void main(String[] args) {
ArrayList<byte[]> list = new ArrayList<>();
while(true) {byte[] arr = new byte[100];
list.add(arr);
try {
Thread.sleep(10);
} catch(InterruptedException e) { e.printStackTrace(); }}}}Copy the code
We set the JVM startup parameters
-Xms10m -Xmx10m -XX:+PrintGCDetails
Copy the code
First of all, we will store three 2M arrays in Eden area, and then the next 4M arrays will not be able to be stored, because there is only 2M remaining space in Eden area. Then a Young GC operation will be performed to store the contents of the original Eden area into Survivor area. But if the Survivor zone does not fit, it will directly advance to the Old zone.
Then we store the 4M object into the Eden area
There are several tools available to analyze these GC logs. Common log analysis tools include GCViewer, GCEasy, GCHisto, GCLogViewer, Hpjmeter, Garbagecat, and so on
Garbage collector summary
GC is still in rapid development, the current default option G1 GC is constantly improving, many of the shortcomings we previously thought, such as serial FullGC, Card Table scanning low efficiency, have been greatly improved, for example, after JDK10, FullGC is now running in parallel. In many scenarios, it also performs slightly better than Parallel GC’s Parallel Full GC implementation. Even SerialGC, although relatively old, is not necessarily outdated in its simple design and implementation. Its overhead, no matter GC related data structure overhead or thread overhead, is very small. Therefore, with the rise of cloud computing, in new application scenarios such as Serverless, Serial GC has found a new arena. Unfortunately, CMSGC has been deprecated in JDK9 and removed in JDK14, although it still has a very large user base due to theoretical flaws in its algorithm. **
Welcome to pay attention to the public number Shanma carpenter, I am Xiao Chun brother, engaged in Java back-end development, will be a little front-end, through the continuous output of a series of technical articles to literary friends, if this article can help you, welcome everyone to pay attention to, like, share support, we see you next period!