In-depth understanding of Java Virtual Machines garbage collector

Source: Internet
Author: User

Speaking of garbage collection (garbage collection,gc), most people regard this technique as the companion product of the Java language. In fact, the history of GC is far longer than that of Java, and the 1960 birth of Lisp in MIT was the first language to actually use memory dynamic allocation and garbage collection techniques. When the list is still embryonic, people are thinking about 3 things the GC needs to do:

    • What memory needs to be recycled?
    • When do I recycle?
    • How to recycle?

Although the current dynamic allocation and memory recovery technology has been quite mature, everything seems to enter the "Automation" era, but only its inherent, to let us write each code. Next, the above three questions are revealed.

What memory needs to be recycled?

From the JVM area structure, these zones can be divided into two categories: static memory and dynamic memory. Program counter, virtual machine stack, local method 3 zones are "static", because the memory allocation and recycling of these areas are deterministic, all with the thread, and out of the thread. But the Java heap is not the same as the method area, where memory allocations are uncertain, and only when the program is running can you know which objects are being created, and this part of the memory and recycling is dynamic, and the garbage collector is concerned about this part of memory.

Memory allocation and recycling in the "static" area is clear, but how does the "dynamic" area determine which memory to recycle and which memory should not? As we all know, Java is an object-oriented language, and memory allocations in the "dynamic" memory area heap exist in the "object" unit (after the method area). If you want to recycle, it must be to reclaim which unused objects, then how to determine the object is useless?

Judgment Method 1 : Reference Counting Method

When assigning an object, add a reference counter to the object, and whenever there is a reference to it, the counter value is incremented by 1, and when the reference fails, the counter value is reduced by 1, and any object with counter 0 at any time is no longer in use. Objectively speaking, the reference counting method (Reference counting) implementation is simple, the judgment efficiency is very high, but in the mainstream Java Virtual machine does not choose the reference counting method to manage the memory, the most important reason is that it is difficult to solve the problem of mutual circular reference between objects. For example:

 Public classREFERENCECOUNTINGGC { PublicObject instance =NULL; Private byte[] Bigsize =New byte[2*1024*1024];  Public Static voidTESTGC () {REFERENCECOUNTINGGC Obja=NewREFERENCECOUNTINGGC (); REFERENCECOUNTINGGC OBJB=NewREFERENCECOUNTINGGC (); Obja.instance=OBJB; Objb.instance=Obja; Obja=NULL; OBJB=NULL;    System.GC (); }}

Judgment Method 2 : Accessibility analysis Algorithm

The basic idea of the reachability analysis is that through a series of objects called "GC Roots" as the starting point, the search is traversed by a path called the reference chain (Reference Chain), when an object to the GC Roots This object is not available when no reference chain is connected (that is, the GC roots to this object is unreachable). As shown in the following:

Objects Object5, OBJECT6, Object7 are associated with each other, but they are not accessible to GC roots, so they will be judged as recyclable objects. In the Java language, the objects that can be used as GC roots include the following:

    • The object referenced in the virtual machine stack (the local variable table in the stack frame).
    • The object referenced by the class static property in the method area.
    • The object referenced by the constant in the method area.
    • The object referenced by JNI (that is, generally speaking, the native method) in the local method stack.

Both the reference counting method and the accessibility analysis algorithm use the concept of reference, starting with JDK1.2, Java extends the concept of references into strong references (strong Reference), soft references (Softe Reference), weak references (Weak Reference), virtual reference (Phantom Reference) Four kinds, enhance the applicability of the reference.

    • A strong reference is a common reference in program code, such as "Object obj = new Object ()", where only strong references exist, and the garbage collector never reclaims the referenced objects.
    • Soft references are also used to describe some useful, but not necessary, objects. For objects associated with soft references, these objects are then listed in the collection scope for a second collection before the system is about to occur with a memory overflow exception. If this collection does not have enough memory, a memory overflow exception will be thrown.
    • A weak reference is also used to describe a non-essential object, but its strength is weaker than a soft reference, and the object associated with the weak reference only survives until the next garbage collection occurs. However, garbage collection works, regardless of whether the current memory is sufficient, will reclaim only the weak reference associated with the object.
    • A virtual reference, also known as a phantom reference or phantom Reference, is the weakest reference relationship. Whether an object has a virtual reference exists, does not affect its lifetime at all, and cannot obtain an object instance through a virtual reference. The only purpose of setting a virtual reference association for an object is to be able to receive a system notification when the object is reclaimed by the collector. Because the Finalize function (later speaking) is called uncertainty, it is impossible to predict whether the object will be recycled, where the virtual reference will work.

Even those unreachable in the Accessibility analysis algorithm are not "immortal", at this time they are temporarily in the probation stage, to truly declare an object to die, at least two times to go through the marking process. For the first time, after the accessibility analysis, it is found that there is no reference chain connected to GC roots and one filter at a time, if it is not necessary to filter out the Finalize method (the current object does not overwrite the Finalize method or the method has been executed, Note: The Finalize method will only be called once for the entire object life cycle. An object confirming that there is no need to perform a Finalize method is dead. If it is necessary to execute the object of the Finalize method, the object is placed in a queue called F-queue, and a virtual machine automatically establishes a low-priority finalizer thread to execute it later. This is also the end of the object's self-help time, it can be in the Finalize method to assign themselves (this) to a class variable or the object's member variable from the garbage collection. However, it has been mentioned in "virtual reference" that there is uncertainty in the invocation of this finalize method. Because the virtual machine does not promise to wait for the entire f-queue to execute, because it does not rule out that some of the Finalize method has a dead loop and other extreme situations cause f-queue to wait forever. So, the Finalize () method is the last chance for an object to escape death, but it is not necessarily called and is only called once throughout the life cycle, and later the GC will make a second small-scale mark on the objects in the F-queue. If you do not escape successfully, then this object will really be recycled.

Method Area Recall

Garbage collection of the method area (or permanent generation in the Hotspot virtual machine) mainly reclaims two parts: obsolete constants and useless classes. But the recovery efficiency of the permanent generation is far from the recycling efficiency of the heap. Judging whether a constant is "obsolete" is very similar to the object judged in the heap, and it is hard to judge whether a class is a "useless class" condition:

    • All instances of the class have been reclaimed, that is, no instances of the class exist in the Java heap.
    • The ClassLoader that loaded the class have been recycled.
    • The corresponding Java.lang.Class object of this class is not referenced anywhere and cannot be used to access the class's methods at any place.

However, it is important to note that even if the above three conditions are met, it may not necessarily be recycled. Perhaps the effect of the permanent generation is not ideal, in the JDK8, there is no concept of a permanent generation, the original area was placed in the local memory.

When do I recycle?

The previous section covered what objects need to be recycled, so this section is mainly about when these objects are recycled. In mainstream languages (like Java), the use of accessibility analysis algorithms is used to determine the survival of objects. The accessibility analysis algorithm is based on the downward correlation of GC roots to find objects that are not associated. If area-by-region inspection is time-consuming, the current mainstream Java virtual machine (such as hotspot) uses an accurate GC. Hotspot uses a data structure called Oopmap to record which specific addresses of the stack and register at some point are reference addresses, so that the GC roots can be quickly found to mark operations on objects. The "one moment" here is the famous stop the world. Virtual machines in order to analyze GC roots this work must be done in a snapshot that ensures consistency, where "consistency" means that the entire execution system looks like it was frozen at a certain point in time throughout the analysis-it's called a security point. Of course, when the program executes, it does not stop at all places to start the GC and can only be paused when the security point is reached. There are also provisions for the siting of safety sites, and the selection is basically based on whether the program "has characteristics that allow the program to execute for a long time". The most obvious feature of long-time execution here is instruction-column multiplexing, such as method invocations, loop jumps, exception jumps, and so on.

Virtual machine in order to allow all threads to "run" to the security point to pause, designed two scenarios: preemptive interrupt and active interrupt. The preemptive interrupt is when the virtual machine occurs GC, all the threads are interrupted first, if the thread break occurs in the place of the security point, then restore the threads, let it "run" to the security point. This method is now more used. The active interrupt is simply a flag when the virtual machine needs a GC, and when each thread executes to a secure point, it actively polls the flag and discovers that the interrupt flag is true when it interrupts its own suspension.

The security point mechanism only guarantees that the program at execution can receive a "notification", but what about a program that does not execute, such as a program that waits for CPU time? For example, when a thread is in a sleep state or a blocked state, the thread cannot respond to the JVM's interrupt forcing. In this case, the JVM uses the security zone (safe region) to resolve. A security zone is a piece of code in which the reference relationship does not change, and it is safe to start the GC anywhere in the region. For example, when a thread executes code in a security zone, it first identifies itself as having entered a security zone. Then when the JVM launches the GC, it does not have to take care of those threads that have already been labeled safe in the state. When these threads leave the security zone, it also checks to see if the system has completed the root node enumeration (or the entire GC process) to continue, otherwise it must wait until a signal can safely leave the security zone.

How to recycle?

The garbage collector is the implementation of garbage collection, which is the garbage collector's method, which recycles the useless objects described above. Therefore, before introducing the garbage collector, it is helpful to understand the garbage collection algorithms, which can be used for subsequent garbage collector implementations.

Mark- Clear (Mark-sweep ) Algorithm

This is the most basic algorithm, like its name, the algorithm is divided into "mark" and "clear" two stages: first Mark all the objects that need to be recycled (such as which memory needs to reclaim the described object), after the mark is complete, the unified collection of all tagged objects, as shown in:

Disadvantage: One is the efficiency problem, marking and clearing two processes is not efficient; the other is the space problem, Mark clear regret produces a large number of discontinuous memory fragments, which may cause subsequent inability to allocate large objects, causing the garbage collection action to be triggered again.

Replication Algorithms

To the disadvantage of the tag-purge algorithm, the replication algorithm divides the available memory capacity into two blocks of equal size, using only one piece at a time. When a piece of memory is exhausted, copy the surviving object to the other. Then clean up the used memory space once, as shown in:

Cons: Use less than half of the original memory.

Today's commercial virtual machines are using this collection algorithm to recover the new generation, there is an enterprise analysis of the fact that there is no need to divide the memory by 1:1, because most of the new generation of objects are "facing the birth of the dead." Therefore, the default Eden and survivor size ratio for the hotspot virtual machine is 8:1. A piece of Eden and two pieces of survivor, each using a piece of Eden and a survivor, which means only 10% is wasted. If another piece of survivor cannot hold the object of the last garbage collection, those objects will enter the old age through the "guarantee mechanism".

Mark- Finishing (Mark-compact ) Algorithm

The replication algorithm is generally a low survival of the object of a recovery operation, but for the high survival of the object memory area (the old age), the effect is not so ideal, the marker-finishing algorithm was born. The tag-collation algorithm and the tag-purge algorithm are almost all initially tagged for the object being reclaimed, but instead of being cleaned directly from the object, all surviving objects are moved to one end and the memory outside the end boundary is cleaned up directly, as shown in:

Generational collection Algorithms

The current commercial virtual machine garbage collection uses the "generational collection" (generational Collection) algorithm, which only divides the memory into several blocks according to the different life cycle of the object, generally divides the Java heap into the new generation and the era, This allows the most appropriate collection algorithm to be used for the characteristics of each age.

Now that we've covered the garbage collection algorithm, we'll start with the garbage collector that implements these algorithms:

Serial Collecting Device

The serial collector is the most basic and longest-growing collector. This collector is a single-threaded collector that must suspend the work of other threads when it works, that is, stop the world. This display is its disadvantage, which is also the way the garbage collector has been working. Of course, the serial collector is simple and efficient compared to other single-thread collectors. For desktop applications, there is not too much management memory allocated and the pause time can be controlled up to dozens of milliseconds up to 100 milliseconds. Therefore, the serial collector is a good choice for virtual machines running in client mode. Run the serial with the serial old collector (follow up):

parnew Collecting Device

The Parnew collector is actually the multi-threaded version of the serial collector (which works better with multiple CPUs), and the process for parnew to combine the serial old collector (subsequent introduction):

The Parnew collector does not have much innovation for serial, but it is the preferred new generation collector for many virtual machines running in server mode, since only the serial collector can work with the CMS collector (subsequent introductions). Therefore, it is regrettable that the CMS as a collector of the old age, but can not be JDK1.4 with the existing new generation collector parallel scavenge work together.

Parallel Scavenge Collecting Device

Parallel Scavenge Collector is a new generation collector, it is also using the copy algorithm of the collector, but also a parallel multi-threaded collector, it looks similar to parnew. But the parallel scavenge collector differs from other collectors in that the focus of collectors, such as the CMS, is to minimize the downtime of user threads when garbage collection occurs, while parallel The target of the scavenge collector is to achieve a controllable throughput (throughput). The so-called throughput is the ratio of the amount of time the CPU spends running user code to the total CPU time, that is, throughput = Run user code time/(run user code time + garbage collection time), the virtual machine runs for a total of 100 minutes, the garbage collection takes 1 minutes, and the throughput is 99%.

The Parallel scavenge collector can control the maximum garbage collection pause time and the-xx:gctimeratio parameters that directly set the throughput size through the-xx:maxgcpausemillis parameter. The Parallel scavenge collector also has a-xx:useadaptivesizepolicy switch parameter that does not need to manually specify the size of the Cenozoic, the ratio of Eden to the survivor area, the age of the old age, and other details when the parameter is opened. The virtual opportunity collects performance monitoring information according to the current system operation, and dynamically adjusts the relevant parameters. This regulation is called adaptive Adjustment Strategy, is also an important difference between parallel scavenge collector and parnew collector.

Serial Old Collecting Device

Serial old is an older collector, it is also a single-threaded collector, using the "tag-collation" algorithm. The main meaning of this collector is also to use the virtual machine in client mode. In the case of server mode, it has two main uses: one for use with the parallel scavenge collector in JDK1.5 and previous versions, and the other is to act as a fallback for the CMS collector, where the concurrency collection occurs concurrent used when Mode failure.

Parallel Old Collecting Device

Parallel old is an older version of the Parallel scavenge collector, using multithreading and the "mark-and-organize" algorithm. This collector was only started in JDK1.6, and before that, the new generation of parallel scavenge collectors had been in a state of relative embarrassment. The reason is that if the new generation chooses the parallel scavenge collector, the older generation has no choice but to serial old collector (because it cannot be used in conjunction with CMS). In the CPU era, due to the "drag" of the serial old collector in the performance of the server, the use of the parallel scavenge collector may not be able to achieve maximum throughput in the overall application. Until the advent of the parallel old collector, the "throughput first" collector had a more veritable combination of applications. The parallel scavenge plus parallel old collector can be prioritized in the context of throughput and CPU resource sensitivity, as shown in:

CMS Collecting Device

The CMS (Concurrent Mark Sweep) collector is a collector that targets the shortest recovery pause time. At present, a large part of the Java application focus on the Internet or B/s system services, such applications pay particular attention to the response speed of the service, hope that the system pauses the shortest time, in order to bring a better experience to users. As can be seen from the name, the CMS collector is implemented based on the "tag-purge" algorithm. But its actual operation is more complex for the previous collectors, the whole process is divided into 4 steps:

    • Initial tag (CMS initial mark)
    • Concurrency token (CMS concurrent mark)
    • Re-tagging (CMS remark)
    • Concurrent Purge (CMS concurrent sweep)

Where the initial tag, re-tagging these two steps still need "Stop the World". The initial tag simply marks the object that the GC Roots can directly relate to, is fast, and the concurrent tagging phase is the process of GC Roots tracing, while the re-tagging phase is to fix the tag record of the part of the object that the markup produces when the user program continues to work during the concurrency tag. The pause time in this phase is generally slightly longer than the initial marker phase, but is much shorter than the concurrent marker time. Because the most time-consuming concurrency token and the concurrent cleanup process of the collector thread can work with the user thread throughout the process, the memory recycling process for the CMS collector, in general, is performed concurrently with the user thread (note the concept of concurrency and parallelism), as shown in:

CMS is an excellent collector, but it is far from the perfect level, it has the following 3 obvious drawbacks:

    • The CMS collector is very sensitive to CPU resources. Because in the concurrency phase, it consumes a portion of the thread (or CPU resources) and causes the application to slow down and the total throughput is reduced.
    • The CMS collector is unable to handle floating garbage, and a "Concurrent Mode Failure" failure may occur resulting in another full GC. Because the CMS concurrent cleanup phase of the user thread is still running, along with the program run naturally there will be new garbage constantly generated, this part of the garbage in the marking process, the CMS can not be processed at the time of the collection, and had to wait for the next GC to clean up, this part of the garbage is called "floating garbage."
    • Finally, the CMS is a collector based on the "tag-clear" algorithm, which means that there is a lot of space fragmentation at the end of the collection. To solve this problem, the CMS collector provides a-xx:+usecmscompactatfullcolletion switch parameter (which is turned on by default) to enable the memory fragmentation consolidation process when the CMS collector is not up to full GC. The process of memory collation is not concurrent, the space fragmentation problem is not, but the time to pause must not be longer. The Virtual Machine Designer also provides another parameter,-xx:cmsfullgcsbeforecompaction, which is used to set how many times the uncompressed full GC is followed by a compressed (default of 0, which means defragmentation every time it enters the full GC).

G1 Collecting Device

The G1 (garbage first) collector is one of the most cutting-edge results of today's collector technology, starting with the early acsess version of the G1 collector from the JDK 6U14 for developers to experiment, try out, and start G1 the collector's experimental The status persisted for several years until the Jdk7u4,sun company considered it to be commercially mature enough to remove the "experimental" logo. The G1 is a garbage collector for service-side applications. The mission assigned to it by the Hotspot development team is to replace the CMS collectors released in JDK1.5 in the future. Compared with other collectors, G1 has the following features:

    • Parallel and Concurrency: similar to CMS.
    • Generational collection: Generational concepts remain in the G1. Although G1 can manage the entire GC heap independently without the need for other collector mates, it can handle newly created objects in different ways and old objects that have survived for a period of time to get better collection results. In other words, G1 can manage the new generation and the old age.
    • Spatial integration: Since G1 uses the concept of isolated regions (region), G1 is based on the "mark-and-Finish" algorithm, which is based on a "copy" algorithm, which is implemented from a local (two regional) basis, but in any case, Both of these algorithms mean that memory space fragmentation does not occur during G1 operations.
    • Predictable pauses: This is another big advantage of G1 relative to the CMS, reducing the pause time is a common concern for G1 and CMS, but G1 in addition to the pursuit of low pauses, but also to establish a predictable pause time model, allowing the use of this explicitly specify a length of M milliseconds in the time fragment, The time spent on garbage collection must not exceed n milliseconds.

In contrast to other collectors, the G1 change is that it divides the entire Java heap into separate regions of equal size (region), while preserving the concept of the Cenozoic and the coming years, but the new generation and the old age are no longer physically isolated, they are part of the region (no continuous) collection. Also, to avoid full heap scanning, G1 uses the remembered set to manage related object reference information. When memory is reclaimed, adding the remembered set to the enumeration scope of the GC root node guarantees that no full heap scan will be missed.

If you do not calculate the operation of maintaining remembered set, the operation of the G1 collector can be broadly divided into the following steps:

    • Initial tag (Initial Making)
    • Concurrency token (Concurrent marking)
    • Final mark (Final marking)
    • Filter collection (Live Data counting and evacuation)

It seems to be somewhat similar to how the CMS collector works, but it does. The initial phase simply marks the object that the GC roots can directly relate to, and modifies the value of the Tams (next Top Mark Start), allowing the next stage of the user program to run concurrently, creating a new object in the correctly available region, which requires a stalled thread, but takes a short time. The concurrency tagging phase begins with the GC roots for accessibility analysis of objects in the heap, identifying the surviving objects, which take a long time but can run concurrently with the user thread. The final tagging phase requires that the data of the remembered set logs be merged into the remembered set, which requires a stalled thread but can be executed in parallel. The final filter recovery phase first sorts the recovery value and cost of each region, according to the desired GC pause time to make the recycling plan, this process also needs to pause the thread, but Sun revealed that this phase can also be done concurrently, but considering that the pause thread will greatly improve the collection efficiency, So choose a pause. To run for the G1 collector:

In-depth understanding of Java Virtual Machines garbage collector

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.