In-depth understanding of Java garbage collection mechanism

Source: Internet
Author: User

First, why the need for garbage collection

Without garbage collection, memory will be consumed sooner or later because we are constantly allocating memory space without recycling. Unless the memory is infinitely large, we can be self-willed and not recycled, but that is not the case. Therefore, garbage collection is a must.

memory leak : Refers to the memory space is not recycled after use, in the general case, without involving complex data structures, Java memory leakage is manifested as a memory object life cycle beyond the length of time the program needs it, we have to also call it "Object free";

Second, which memory needs to be recycled?

Which memory needs to be recycled is the first problem to be considered in the garbage collection mechanism, so-called "garbage to be recycled" is nothing more than an object that can no longer be used in any way. So how do I find these objects?

The Java language Specification does not explicitly describe which garbage collection algorithm the JVM uses, but any garbage collection algorithm typically does two basic things: (1) Discovers useless information objects, (2) reclaims memory space occupied by useless objects. Make the space available for reuse by the program.

1. Reference counting method

The implementation of this algorithm is to add a reference counter to the object, whenever a place refers to the object, the counter value +1; When the reference fails, the counter value-1. Any object with a count value of 0 at any time is impossible to be used again. This algorithm uses a lot of scenarios, but the algorithm is not used in Java because it is difficult to solve the case of mutual reference between objects. Look at the code:

/** * Virtual machine Parameters:-verbose:gc */public class referencecountinggc{    private Object instance = null;    private static final int _1mb = 1024x768 *;        /** the only function of this member property is to occupy a bit of memory */    private byte[] bigsize = new byte[2 * _1MB];        public static void Main (string[] args)    {        REFERENCECOUNTINGGC objecta = new REFERENCECOUNTINGGC ();        REFERENCECOUNTINGGC OBJECTB = new REFERENCECOUNTINGGC ();        Objecta.instance = OBJECTB;        Objectb.instance = objecta;        Objecta = null;        OBJECTB = null;                System.GC ();    }}

Look at the results of the operation:

[GC 4417k->288k (61440K), 0.0013498 secs] [Full GC 288k->194k (61440K), 0.0094790 secs]

See, two objects are referenced to each other, but the virtual machine still reclaims the two objects, which also means that the virtual machine does not use reference counting to determine whether the object survives.

2. Accessibility Analysis method

The basic idea of this algorithm is to use a series of objects called "GC Roots" as the starting point, to search down from these nodes, the path of the search is called the reference chain, when an object to the GC Roots no reference chain (that is, the GC Roots to the object unreachable), it proves that this object is not available.

So the question comes again, how to choose Gcroots object? In the Java language, the objects that can be used as gcroots include the following:

(1). The virtual machine stack (the local variable area in the stack frame, also called the local variable table) refers to the object.

(2). The object referenced by the class static property in the method area.

(3). The object referenced by a constant in the method area.

(4). The object referenced by the JNI (native method) in the local method stack.

Here is an example of a gcroots, such as a reference chain for gcroots.

From the figure, Obj8, Obj9, obj10 have no reference chain to the Gcroots object, even if there is a reference chain between Obj9 and Obj10, they will be treated as garbage, can be recycled.

Three or four types of reference states

Before JDK1.2, the definition referenced in Java was traditional: if the value stored in the reference type's data represents the starting address of another piece of memory, it is said that this memory represents a reference. This definition is purely, but too narrow, that an object is either referenced or not referenced in two states. We want to describe a class of objects that can be kept in memory when the memory space is sufficient, and if the memory space is still very tense after garbage collection, you can discard the objects. Many of the system's caching capabilities are consistent with this scenario. After JDK1.2, Java extends the concept of references into strong references, soft references, weak references, and 4 of virtual references, which in turn weaken the 4 reference intensities.

1. Strong references

A reference commonly found in code like "Object obj = new Object ()", as long as a strong reference exists, the garbage collector never reclaims the referenced object.

2. Soft reference

Describes some objects that are useful but not necessary. These objects will be listed in the Recycle range for two recoveries before the system will have a memory overflow exception. If this collection does not have enough memory, a memory overflow exception will be thrown. The class SoftReference in Java represents a soft reference.

3. Weak references

Describes non-required objects. Objects that are associated with a weak reference only survive until the next garbage collection, and after the garbage collector has worked, the object associated with the weak reference is reclaimed, regardless of the current memory adequacy. The class WeakReference table in Java is a weakness reference.

4. Virtual Reference

The only purpose of this reference is to receive a system notification when the object is reclaimed by the collector, the object that is associated with the virtual reference, and its time to live is completely irrelevant. The class phantomreference in Java represents a virtual reference.

For the accessibility analysis algorithm, the unreachable object is not "undead", and to pronounce an object dead, at least two marker stages are required.

1. If the object finds no chain of references connected to gcroots after the accessibility analysis, the object is first marked and filtered once, and the filter condition is whether it is necessary to execute the object's Finalize method, If the object does not overwrite the Finalize method or if the Finalize method has been executed by the virtual machine, it is treated as a finalize method that does not have to execute the object, that is, the object will be reclaimed. Conversely, if the object overrides the Finalize method and the Finalize method is not executed, then the object is placed in a queue called F-queue, which is then executed automatically by the virtual machine, with a low priority finalizer thread. The virtual machine does not have to wait for the thread to finish, that is, the virtual machine is only responsible for establishing the thread, and the other thing is handing it over.

2. F-queue the object in the second time, if the object in the Finalize method to save itself, that is, associated with the Gcroots reference chain, such as assigning the This keyword to other variables, then the second time the object will be removed from the collection of "will be recycled", If the object still does not save itself, it will be recycled. The following code shows how an object saves itself in the Finalize method, but it can only save itself once and the second time it is recycled. The specific code is as follows:

Package com.demo;/* * This code demonstrates two points: * 1. The object can be saved by GC again * 2. This chance of self-help is only one time, because the Finalize () method of an object is automatically called only once by the system * */public class Final    IZEESCAPEGC {public String name;    public static FINALIZEESCAPEGC Save_hook = null;    Public FINALIZEESCAPEGC (String name) {this.name = name;    } public void IsAlive () {System.out.println ("Yes, I am still alive:)");        } @Override protected void Finalize () throws Throwable {super.finalize ();        System.out.println ("Finalize Method executed!");        System.out.println (this);    Finalizeescapegc.save_hook = this;    } @Override Public String toString () {return name; public static void Main (string[] args) throws interruptedexception {Save_hook = new FINALIZEESCAPEGC ("LEESF")        ;        System.out.println (Save_hook);        The object saves itself for the first time Save_hook = null;        System.out.println (Save_hook);        System.GC ();    Because the Finalize method has a low priority, pause for 0.5 seconds to wait for it to Thread.Sleep (500);    if (Save_hook! = null) {save_hook.isalive ();        } else {System.out.println ("No, I am Dead: (");        }//The code below is exactly the same as above, but this time it failed.//The Finalize method of an object is only called once save_hook = null;        System.GC ();        Because the Finalize method has a low priority, pause for 0.5 seconds to wait for it to Thread.Sleep (500);        if (Save_hook! = null) {save_hook.isalive ();        } else {System.out.println ("No, I am Dead: ("); }    }}

The results of the operation are as follows:

Leesfnullfinalize method Executed!leesfyes, I am still alive:) No, I am dead: (

The result shows that the object saved itself once and the second did not succeed because the Finalize method of the object was called at most by the virtual machine. Furthermore, we can tell from the result that the reference to this (the first item in the local variable table) of a heap object will always be present, and the this reference can be assigned to other variables in the body of the method, so that the objects in the heap can be referenced by other variables, i.e. they will not be recycled.

Iv. garbage collection in the method area

The garbage collection of the method area mainly recycles two parts: 1. Obsolete constants. 2. Useless classes. Since garbage collection is done, it is necessary to determine which are obsolete constants and which are useless classes.

How to determine the obsolete constants? In the case of literal recycling, if a string "ABC" has entered a constant pool, but the current system does not have any string object referencing the literal called "abc", then "ABC" will be moved out of the constant pool if garbage collection occurs and is necessary. The symbolic references to other classes (interfaces), methods, and fields in a constant pool are similar.

How to judge a useless class? The following three conditions need to be met

1. All instances of the class have been reclaimed, that is, no instances of the class exist in the Java heap.

2. The classloader that loaded the class have been recycled.

3. The corresponding Java.lang.Class object of this class is not referenced anywhere, and the method of accessing the class can be accessed anywhere by reflection.

Classes that meet the above three criteria can be garbage collected, but are not useless to be recycled, and the virtual machine provides some parameters for us to configure.

Five, garbage collection algorithm

1. Mark-Clear (mark-sweep) algorithm

This is the most basic algorithm, the tag-purge algorithm is like its name, divided into "mark" and "clear" two stages: first mark out all the objects that need to be recycled, after the mark is complete, the unified collection of all tagged objects. The shortcomings of this algorithm are mainly embodied in efficiency and space, from the point of view of efficiency, the efficiency of marking and eliminating two processes is not high; from a space point of view, a large number of discontinuous memory fragments are generated after the mark is cleared, and too much memory fragmentation can cause the program to run later when a larger object needs to be allocated. Unable to find enough contiguous memory to trigger a garbage collection action in advance. Mark-Clear algorithm execution process as shown:

2. Copy (Copying) algorithm

The replication algorithm is designed to solve the efficiency problem, it divides the available memory into two pieces, one at a time, and when the memory is used up, copies the surviving objects to the other, then cleans up the memory space that has been used once. In this way, you only need to collect the entire half of the memory, memory allocation is not necessary to consider the complexity of memory fragmentation, only need to move the pointer, in order to allocate. The execution process of the replication algorithm

However, this algorithm has a drawback, memory reduction for the original half, so the cost is too high . Today's commercial virtual machines use this algorithm to reclaim the new generation , but the study shows that the 1:1 ratio is very unscientific, so the new generation of memory is divided into a larger Eden space and two smaller survivor spaces, Use Eden and one piece of survivor at a time. each time a collection is made, the objects that are still alive in Eden and survivor are copied once to another survivor space, and finally the Eden and the survivor space just used are cleared. The default Eden and survivor areas of the hotspot virtual machine are proportional to 8:1, meaning that the available memory space for each Cenozoic is 90% of the total cenozoic capacity. Of course, there is no way to guarantee that only a few 10% of the objects per collection will survive, and when survivor space is not enough, it is necessary to rely on the old age for distribution guarantees (Handle Promotion).

3, marking-finishing (mark-compact) algorithm

The replication algorithm is very inefficient in scenarios where the object has a high survival rate and a large number of replication operations are performed. In the event that object 100% survives, additional space is required for the allocation guarantee. The old age is not easy to be recycled objects, the object survival rate is high, so generally can not directly select the replication algorithm. According to the characteristics of the old age, someone proposed another marker-collation algorithm, the same process as the tag-purge algorithm, but instead of cleaning up the recyclable objects directly, all the surviving objects are moved to one end, and then the memory outside the boundary is cleared directly. The work process of marker-collation algorithm

4, Generational collection algorithm

Use a graph to summarize the layout of the heap memory according to the above content

Modern commercial virtual machines are basically using generational collection algorithms for garbage collection. This algorithm is nothing special, but the combination of the above content, according to the different life cycle of the object to divide the memory into several pieces, and then according to the characteristics of each block using the most appropriate collection algorithm. A large number of objects die, few objects survive (Cenozoic), using replication algorithms, low replication costs, high object survival, no additional space for allocation guarantees (old age), using the tag-cleanup algorithm or marker-collation algorithm.

Six, garbage collector

The garbage collector is the concrete realization of the theoretical knowledge mentioned above. The garbage collectors provided by different virtual machines can be quite different, and we are using all the collectors contained in the Hotspot,hotspot virtual machine

Shows 7 collectors that act on different generations, and if there is a connection between the two collectors, that means they can be used with each other. The area in which the virtual machine is located indicates whether it belongs to the new generation collector or the old collector. To say more, we must make a clear point: there is no best garbage collector, there is no universal collector, can only choose the most suitable for the specific application of the collector. This is why the hotspot is implementing so many collectors. OK, one of the following looks at the collector.

1. Serial Collector

The most basic, longest-growing collector, a single-threaded collector with a copy algorithm, which means that it only uses one CPU or one thread to do garbage collection, and on the other hand, it must suspend all work of other threads when it is garbage collected. Until the end of its collection . The latter means that it is unacceptable for many applications to have all the threads of the user's normal work stopped when the user is not visible. But in fact, so far, theserial collector is still the default Cenozoic collector running in client mode for virtual machines because it is simple and efficient. In a user desktop scenario, the memory assigned to the virtual machine management is generally not very large, and collecting a few 10 trillion or even one hundred or two hundred trillion of new generation pauses in dozens of milliseconds for up to 100 milliseconds, which is perfectly acceptable as long as it does not occur frequently. The serial collector runs as shown in the following procedure:

Description: 1. Need STW (Stop the World), pause for a long time. 2. Simple and efficient, for a single CPU environment, the serial collector can obtain the highest single-thread collection efficiency due to the lack of thread interaction overhead.

2. Parnew Collector

The parnew collector is actually a multithreaded version of the serial collector , with the exception of multiple threads for garbage collection, the same behavior as the serial collector, including the use of a copy algorithm. The Parnew collector does not have much innovation in addition to multithreading and the serial collector, but it is the new generation collector of choice for virtual machines in server mode , one of the important and performance-independent reasons is that, in addition to the serial collector, Currently only it can work with the CMS collector (see figure). The CMS collector is a garbage collector that can almost be considered epoch-making because it first implements a garbage collection thread that basically works with the user thread at the same time. The Parnew collector has absolutely no better effect than the serial collector in a single CPU environment, and even due to the overhead of thread interaction, the collector is not guaranteed to exceed the serial collector in two CPU environments. Of course, as the number of available CPUs increases, it is good for the efficient use of system resources in GC. It opens by default the same number of collection threads as the number of CPUs, and in the case of a very large number of CPUs, you can use the-xx:parallelgcthreads parameter to limit the number of threads that are garbage collected. The Parnew collector runs as shown in the following procedure:

3. Parallel Scavenge Collector

The Parallel scavenge collector is also a new generation collector and is also a collector for replication algorithms, and is also a parallel multi-threaded collector, but it is characterized by a different focus and other collectors. This collector is mainly about the concept of throughput . the focus of collectors, such as CMS, is to minimize the downtime of user threads when garbage collection occurs, while the parallel scavenge collector's goal is to hit a controllable throughput . The so-called throughput means that the CPU is used to run the user code time and CPU total elapsed time ratio, that is, throughput = Run user code time/(run user code time + garbage collection Time), the total running of the virtual machine 100 minutes, garbage collection 1 minutes, the throughput is 99%. Additionally, theParallel scavenge collector is the default garbage collector that the virtual machine runs in server mode .

Short pause time for programs that need to interact with the user, good response speed can improve the user experience, high throughput can be efficient use of CPU time, as soon as possible to complete the operation of the task, mainly for the background operation and do not need too many interactive tasks.

The virtual machine provides-xx:maxgcpausemillis and-xx:gctimeratio two parameters to precisely control the maximum garbage collection pause time and throughput size. However, do not assume that the smaller the better, the shortening of the GC pause time is to sacrifice the throughput and the new generation of space exchange. Due to its close relationship to throughput, theParallel scavenge collector is also known as the throughput priority collector. The Parallel scavenge collector has a-xx:+useadaptivesizepolicy parameter, which is a switch parameter that, when opened, does not need to manually specify details such as the Cenozoic size, Eden Zone, and survivor parameters, The virtual opportunity adjusts these parameters dynamically to provide the most appropriate pause time or maximum throughput based on the performance monitoring information of the current system. If you are not familiar with how the garbage collector works, it is a good idea to give the memory management tuning task to the virtual machine by using the parallel scavenge collector in conjunction with the adaptive throttling strategy when the optimization is more difficult .

4. Serial Old Collector

The old-age version of the serial collector is also a single-threaded collector, with the tag-grooming algorithm, the main meaning of this collector is to use the virtual machine in client mode.

5. Parallel Old Collector

Parallel The old version of the scavenge collector, using multithreading and the "mark-and-organize" algorithm . This collector comes after JDK 1.6, and the "throughput priority collector" finally has a more veritable mix of applications that prioritize the combination of the Parallel scavenge collector +parallel old collector in the context of throughput and CPU resource sensitivity. The running process is as follows:

6. CMS Collector

The CMS (conrrurent Mark Sweep) collector is the collector with the goal of obtaining the shortest recovery pause time. Using the mark-clear algorithm , the collection process is divided into the following four steps:

(1). The initial tag, which marks the object that the gcroots can directly relate to, has a short time.

(2). Concurrent tagging for gcroots tracing (accessibility analysis) process for a long time.

(3). Re-mark, fix the tag record of the part of the object that caused the mark to change during the concurrent tag, and the time is longer.

(4). Concurrent cleanup, reclaim memory space for a long time.

The two phases of concurrent tagging and concurrent cleanup take the longest, but can be executed concurrently with the user thread. The running process is as follows:

Description: 1. Very sensitive to CPU resources, which can cause applications to slow down and throughput rates down. 2. Unable to handle floating garbage, because the user thread is still running in the concurrent cleanup phase, it will naturally generate new garbage, and in this collection can not collect them, only to stay until the next collection, this part of the garbage is floating garbage, and because the user thread execution concurrently, So it is necessary to reserve part of the old age space to provide concurrent collection when the program runs. 3. Due to the use of the tag-purge algorithm, a large amount of memory fragmentation, not conducive to the allocation of large objects, may trigger a full GC in advance. The virtual machine provides a-xx:+usecmscompactatfullcollection parameter to defragment the merge process, which will make the pause time longer, the virtual machine also provides a parameter configuration,-xx:+ Cmsfullgcsbeforecompaction, which is used to set the number of uncompressed full GC executions, followed by a compressed GC.

7. G1 Collector

G1 is one of the most cutting-edge results of current technology development, and the mission assigned to it by the Hotspot development team is to replace the CMS collectors released in JDK1.5 in the future. Compared to other GC collectors, the G1 collector has the following characteristics:

(1). Parallel and concurrency. Use multiple CPUs to shorten the stop time of the world and execute concurrently with the user thread.

(2). Collection of generations. Manages the entire heap independently, but is able to handle new objects in different ways and old objects that have survived for a period of time to get better collection results.

(3). Space integration. Based on the tag-collation algorithm, no memory fragmentation is generated.

(4). Predictable pauses. Can resume predictable pause time model, can let the user explicitly specify in a time fragment length of M milliseconds, consumption in garbage collection time not more than n milliseconds.

The garbage collector before G1, the collection is the whole new generation or the old age, and G1 is no longer the case. With the G1 collector, the memory layout of the Java heap differs greatly from that of other collectors, which divide the entire Java heap into separate, equal-sized regions (region), while preserving the concept of the Cenozoic and older generations, but the Cenozoic and the old are no longer physically isolated, they are both a (Can not be contiguous) a collection of region.

8. Common collector Combinations

Vii. Understanding GC Logs

The log form of each collector is determined by their own implementation, in other words, each collector's log format can be different. However, in order to facilitate the user to read the virtual machine, the log of each collector maintains a certain commonality, to see the following section of the GC log:

[GC [Defnew:310k->194k (2368K), 0.0269163 secs] 310k->194k (7680K), 0.0269513 secs] [times:user=0.00 sys=0.00, real=0.03 secs] [GC [defnew:2242k->0k (2368K), 0.0018814 secs] 2242k->2241k (7680K), 0.0019172 secs] [times:user=0.00 sys=0.00, real=0.00 secs] [Full GC (System) [Tenured:2241k->193k (5312K), 0.0056517 secs] 4289k->193k (7680K), [perm:2950k->2950k (21248K )], 0.0057094 secs] [times:user=0.00 sys=0.00, real=0.00 secs] Heap def New generation total 2432K, used 43K [0x0000000 0052a0000, 0x0000000005540000, 0x0000000006ea0000) Eden Space 2176K, 2% used [0x00000000052a0000, 0X00000000052AAEB8, 0 x00000000054c0000) from space 256K, 0% used [0x00000000054c0000, 0x00000000054c0000, 0x0000000005500000) to space 25 6K, 0% used [0x0000000005500000, 0x0000000005500000, 0x0000000005540000) tenured generation total 5312K, used 193K [0x 0000000006ea0000, 0x00000000073d0000, 0x000000000a6a0000) The space 5312K, 3% used [0x0000000006ea0000, 0x0000000006ed 0730, 0x0000000006ed0800, 0x00000000073d0000) compacting Perm gen Total 21248K, used 2982K [0x000000000a6a0000, 0x000000000b b60000, 0x000000000faa0000) The space 21248K, 14% used [0x000000000a6a0000, 0x000000000a989980, 0x000000000a989a00, 0x0 00000000bb60000) No GKFX spaces configured.

1, the beginning of the log "GC", "full GC" represents the garbage collection of the type of pause, rather than to distinguish between the new generation GC or the old GC. If there is full, this GC stops all other worker threads (Stop-the-world). See that the full GC is written as "full GC (System)", which means that the GC triggered by the call to the System.GC () method is called.

2, "GC" in the next "[Defnew" represents the area where the GC occurs, where the name of the area shown is closely related to the GC collector used, for example, the serial collector used in the previous generation named "Default New Generation", so the display is "[Defnew". If it is a parnew collector, the New generation name will become "[parnew", meaning "Parallel Generation". If the parallel scavenge collector is used, it is called "Psyounggen" by the new generation, and the old and permanent generations are the same, and the name is determined by the collector.

3. "310k->194k (2368K)", "2242k->0k (2368K)" Inside the square brackets, refers to the capacity (total capacity) that has been used in the memory area after the capacity->GC used in the area. The "310k->194k (7680K)", "2242k->2241k (7680K)" Outside the square brackets refers to the capacity that the Java heap has used (total Java heap capacity) after the capacity->GC the Java heap has been used before the GC.

4, then "0.0269163 secs" indicates the time taken by GC in this memory area, in seconds. The final "[times:user=0.00 sys=0.00 real=0.03 secs]" is more specific, user represents the CPU time consumed by the state, the CPU time consumed by the kernel state, and the wall clock time elapsed from the start to the end of the operation. The difference between the next two is that the wall clock time includes a variety of non-operational wait consumption, such as waiting for disk I/O, waiting for thread blocking, and CPU time does not include these times, but when the system has multiple CPUs or multicore, multi-threaded operation will overlay these CPU time, So it is perfectly normal to see the user or sys time exceeding the real time.

5. The "Heap" is followed by a list of the memory of the area of the heap memory in each of the current years.

In-depth understanding of Java garbage collection mechanism

Related Article

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.