Interview Question: Garbage Collection Mechanism

 The blog titled Java Garbage Collection Mechanism gives the impression that garbage collection is specific to the Java language. In fact, Garbage Collection is much older than Java. Garbage collection needs to consider 3 things: what memory needs to be reclaimed, when to reclaim it, and how to reclaim it. With these three questions, let's see how Java implements garbage collection.

  What parts of the runtime data area does Java's garbage collection (GC) mechanism mainly affect? In the previous blog " How the Java Virtual Machine Works ", we introduced that the JVM runtime data area has five areas : program counter, virtual machine stack, local method stack, heap, and method area . Among them, the first three areas are created with the creation of threads, and die with the demise of threads ; the stack frame in the stack systematically performs pop and push operations with the entry and exit . Therefore, these three areas do not need to consider the problem of garbage collection too much. The Java heap and the method area are different. The memory required by multiple implementation classes of an interface may be different, and the memory required by multiple branches in a method may also be different. Only during the running of the program can you know which objects will be created. The allocation and reclamation of this part of the memory are dynamic. Therefore, it is this part of the memory that the garbage collector is concerned about.

  Back to the first thing about garbage collection: what memory needs to be reclaimed? Almost all object instances in the program are stored in the Java heap. Before the garbage collector collects the heap, it first needs to determine which objects are still "alive" and which are "dead". The usual judgment methods include reference counting algorithm and reachability analysis algorithm . The reference counting algorithm adds a reference counter to the object. Whenever a place references it, the counter value is incremented by 1; when the reference is invalid, the counter value is decremented by 1. If the counter value is 0, it means that the object is no longer used (dead). ). However, the Java virtual machine does not use a counting algorithm to manage memory, because the reference counting algorithm is difficult to solve the problem of mutual circular references between objects . The reachability analysis algorithm uses a series of objects called "GC Roots" as the starting nodes, and starts to search down from these nodes, and the path traversed by the search is called the reference chain. When an object has no reference to the GC Roots When the chain is connected, the object is proved to be unavailable (and dead). The objects that can be used as GC Roots are: objects referenced in the virtual machine stack (local variable table in the stack frame), objects referenced by static attributes in the method area, objects referenced by constants in the method area, and objects referenced in the local method stack. The above are all about memory reclamation in the Java heap , and garbage collection in the method area (permanent generation in HotSpot) mainly recycles two parts: abandoned constants and useless classes. To determine whether a constant is an obsolete constant, you only need to determine whether there are still objects that have references to the constant. To judge a useless class, three conditions must be met at the same time : all instances of the class have been recycled, that is, there is no instance of the class in the Java heap; the ClassLoader that loaded the class has been recycled; the corresponding java.lang. The Class object is not referenced anywhere, and the methods of the class cannot be accessed by reflection anywhere.

Garbage Collection Algorithms

  • Mark-Sweep Algorithm (Mark-Sweep Algorithm)

  The algorithm is divided into two parts (marking and clearing). First, all objects that need to be recovered are marked, and all marked objects are uniformly recovered after the marking is completed. The algorithm has two main shortcomings: one is the efficiency problem, the efficiency of the marking and clearing is not high; the other is the space problem, a large number of memory fragments will be generated after the marking and clearing. The execution process of the mark-sweep algorithm is shown in the following figure:

  • replication algorithm

  In order to solve the efficiency problem of mark-sweep algorithm, the copy algorithm divides the available memory into two equal parts and uses only one part of it at a time. When the used part is used up, the surviving objects are copied to one block, and then the used part is used once Clear. This avoids the problem of memory fragmentation, but the utilization of memory space is not high. The replication algorithm executes as follows:

  Today's commercial virtual machines use this method to collect the new generation, because 98% of the objects in the new generation are "morning and dying", so there is no need to allocate memory space according to 1:1, but to divide the memory into larger blocks. Eden space and two smaller Survivor spaces. When recycling, copy the surviving objects in Eden and Survivor to another Survivor space at one time, and finally clear Eden and the used Survivor space. If the surviving object space in Eden and Survivor is larger than the other Survivor space during recycling, these surviving objects can enter the old age directly through the allocation guarantee mechanism.

  • mark-collate algorithm

  The replication algorithm needs to perform more replication operations when the object survival rate is high, and the efficiency will become lower. And the copy algorithm will waste 50% of the memory space. The survival rate of objects in the old age is relatively high, so the replication algorithm cannot be directly used in the old age. According to the characteristics of the high survival rate of objects in the old age, the "mark-sort" algorithm came into being. This algorithm first marks all objects that need to be recycled, then moves the surviving objects to one end, and then directly cleans up the objects outside the end boundary. memory . As shown below:

Generational Collection Algorithm

  The algorithm has no new ideas, but divides the memory into several blocks according to the life cycle of the object. Generally, the Java heap is divided into the new generation and the old generation, so that an appropriate collection algorithm can be adopted according to the characteristics of each generation. For the characteristics of the death of a large number of objects in the new generation, the replication algorithm is selected; for the characteristics of the high survival rate of objects in the old generation , using the Mark-Sweep or Mark-Sweep algorithm for recycling.

garbage collector

  The garbage collector is the specific implementation of the garbage collection algorithm. Let's take a look at all the collectors included in the HotSpot virtual machine after JDK 1.7 Update 14 as shown in the figure below. Let's analyze the garbage collectors as follows.

  • Serial collector, Serial Old collector

  The Serial collector is a single-threaded collector. When a single thread completes the garbage collection and collects garbage, it must stop all other worker threads. The new generation of the Serial collector adopts the replication algorithm for garbage collection. The Serial Old collector uses a mark-and-groom algorithm to suspend all user threads for the old generation. Its working process is as follows:

  • ParNew collector

  The ParNew collector is a multi-threaded version of the Serial collector. Except for using multiple threads for garbage collection, the rest of the behaviors of the Serial collector, such as control parameters, collection algorithms, pauses, and recycling strategies, are exactly the same as those of the Serial collector. Its working process is as follows:

ParNew is the preferred new generation collector for virtual machines in Server mode. In the new generation, in addition to the Serial collector, only the ParNew collector can work with the CMS collector.

  • Parallel Scavenge collector, Parallel Old collector

  The Parallel Scavenge collector is a new generation collector, and it is also a parallel multi-threaded collector using a replication algorithm. It is different from the focus of the ParNew collector. Its goal is to achieve a controllable throughput, throughput = running user code time / (running user code time + garbage collection time). The higher the throughput, the higher the utilization rate of the CPU, the faster the computing task of the program is completed, and it is mainly suitable for tasks that do not require too much interaction in the background. The Parallel Scavenge collector provides two parameters for precise control of throughput, namely the -XX:MaxGCPauseMillis parameter to control the maximum garbage collection pause time and the -XX:GCTimeRatio parameter to directly set the throughput size. Since the Parallel Scavenge collector is closely related to throughput, it is often called a "throughput-first" collector. In addition to the above two parameters, the collector also has the -XX:+UseAdaptiveSizePolicy parameter. After this parameter is turned on, There is no need to manually specify detailed parameters such as the size of the new generation (-Xmn), the ratio of Eden to Survivor (-XX:SurvivorRatio), and the size of the object to be promoted to the old generation (-XX:PretenureSizeThreshold). The virtual machine is based on the operation of the system. Gather performance monitoring information and dynamically adjust these parameters to provide the most appropriate pause time or maximum throughput.

  The Parallel Old collector is an older version of the Parallel Scavenge collector, using multithreading and a mark-and-sort algorithm. Higher throughput can be achieved with a combination of Parallel Old and Parallel Scavenge collectors.

  • CMS collector

  The CMS (Concurrent Mark Sweep) collector is a collector whose goal is to obtain the shortest collection pause time. From the name, the CMS collector is based on the "mark-sweep" algorithm. Its operation process is more complicated than other collectors. The whole process is divided into 4 steps: initial marking, concurrent marking, remarking, and concurrent clearing. Among them, initial marking and re-marking still need to suspend all threads. Initial marking only marks objects to which GC Roots can be directly associated. Concurrent marking is the process of GC Roots Tracing. Remarking is to correct the marking records of the part of the objects whose markings are changed due to the continued operation of the user program during the concurrent marking. The time of this phase is generally slightly longer than the initial marking phase, but much shorter than the concurrent marking. But the collector's longest concurrent mark and concurrent clear can be performed with user threads. The working process is as follows:

  CMS is a concurrent and low-pause collector, but it has three main disadvantages:

1. The CMS collector is very sensitive to CPU resources. Although it will not cause the user thread to stop during the concurrent marking and concurrent cleanup stages, it will occupy a part of the CPU resources and cause the application to slow down and the total throughput will be reduced. The number of recycling threads started by CMS by default is (number of CPUs + 3)/4. When the number of CPUs is low, the impact of CMS on user programs may be greater.

2. The CMS collector cannot handle floating garbage, and a "Concurrent Mode Failure" may occur, resulting in a Full GC. Since the user thread is still running in the concurrent cleanup phase, new garbage will be generated, and the CMS cannot be disposed of in the current collection, and needs to be cleaned up in the next GC. This part of the garbage is floating garbage. It is precisely because the user thread is still executing in the concurrent cleanup phase, that is, enough memory space needs to be reserved for the user thread to use, so the CMS collector cannot wait until the old age is almost completely filled before collecting like other collectors. A part of the space is reserved for program operation during concurrent collection. If the reserved memory cannot meet the needs during the CMS operation, a "Concurrent Mode Failure" failure will occur, thereby triggering the Serial Old collector to perform garbage collection.

3. CMS is a collector based on mark-sweep algorithm, so it will generate memory fragmentation. In order to solve the problem of memory fragmentation, CMS provides a -XX:+UseCMSCompactAtFullCollection switch parameter, which is used to start the process of merging and defragmenting memory fragments when the CMS collector is about to perform a FullGC. The memory defragmentation process cannot be concurrent, so the pause time will be longer. . Therefore, the virtual machine designer also proposed the -XX:CMSFullGCsBeforeCompaction parameter. This parameter is used to set how many times the uncompressed Full GC is executed, followed by a compressed one (the default value is 0, which means that every time it enters a Full GC, the defragmentation).

  • G1 collector

 G1 (Garbage-First) collector is a garbage collector for server-side applications . Compared with other GC collectors, G1 has the following characteristics:

1. Parallelism and concurrency: G1 makes full use of the hardware advantages in a multi-CPU and multi-core environment, and uses multiple CPUs to shorten the pause time. Some other collectors originally need to pause the Java thread to perform GC actions, but the G1 collector can still use concurrent methods. Let the Java program continue to execute.

2. Generational collection: Although G1 can independently manage the entire GC heap without the cooperation of other collectors, it still retains the concept of generation. It can handle newly created objects and old objects that have survived for a while and survived multiple GCs in a different way to get better collection results.

3. Spatial integration: Different from the "marking-cleaning" algorithm of CMS, G1 is a collector based on the "marking and sorting" algorithm as a whole; from a local point of view, it is based on the "copy" algorithm.

4. Predictable pause: This is another big advantage of G1 over CMS. Reducing pause time is a common concern of G1 and CMS, but in addition to pursuing low pause, G1 can also establish a predictable pause time model, which can Let the user explicitly specify that in a time slice of length M milliseconds, the time spent on garbage collection must not exceed N milliseconds.

  The collection scope of other collectors is the new generation or the old generation. When using the G1 collector, the Java heap memory layout is very different from other collectors. It divides the Java heap into multiple independent areas of equal size, although it retains The concept of the new generation and the old generation, but the new generation and the old generation are no longer physically isolated, they are a collection of a part of the Region.

  The reason why the G1 collector can model predictable pause times is that it can systematically avoid garbage collections on the entire heap. G1 tracks the value of the garbage accumulation in each Region (the amount of space required for recycling and the experience value of the time required for recycling), maintains a priority list in the background, and recycles the Region with the largest value first according to the allowed collection time each time. This improves the collection efficiency as high as possible within a limited time.

  G1 "breaks the memory into zero", but each Region is not irrelevant, so when garbage collection is performed on a Region, when the reachability of the object is determined to determine whether the object is alive, does it need to scan the entire Java Does the heap guarantee correctness? In fact, in the G1 collector, for object references between Regions, the virtual machine uses the Remembered Set to avoid scanning the full heap. Each Region has a Remembered Set. When the virtual machine discovers that the program writes to the reference type data, it will generate a Write Barrier to temporarily interrupt the write operation, and check whether the object referenced by the Reference is in a different Region. If so, then The related reference information is recorded in the Remembered Set of the Region to which the referenced object belongs through CardTable. When performing memory reclamation, adding a Remembered Set to the enumeration range of the GC root node can ensure that there will be no omissions in the full heap scan.

  If the operation of maintaining the Remembered Set is not calculated, the operation of the G1 collector is roughly divided into four steps: initial marking, concurrent marking, final marking, and screening and recycling. The initial marking stage is just to mark the objects that GC Roots can directly associate with, and modify the value of TAMS (Next Top at Mark Start), so that when the user program runs concurrently in the next stage, new objects can be created in the correct available Regions. This stage needs to pause the thread, but the time is very short. The concurrent marking phase is to analyze the reachability of objects in the heap from the GC Roots to find out the surviving objects. This phase takes a long time, but it can be executed concurrently with the user program. The final marking phase is to correct the part of the marking record that changes the marking due to the user program continuing to operate during the concurrent marking period. The virtual machine records the object changes during this period in the thread Remembered Set Logs. The final marking stage needs to merge the data of the Remembered Set Logs into the Remembered Set. This stage needs to pause the thread, but it can be executed in parallel. Finally, in the screening and recycling stage, the recycling value and cost of each Region are sorted first. Develop a recycling schedule based on the user's desired GC pause time.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325522954&siteId=291194637