JVM: memory allocation and recovery strategies

Java technology system advocated in the final automatic memory management can be attributed to automation solves two problems: memory allocation to object to the object memory allocation and recovery.

Memory allocation object, to the general direction of speaking, is allocated on the heap (but possibly break through the JIT compiler after a scalar type and indirect distribution on the stack), the main object is allocated on the new generation of the Eden area, if you started local thread allocation buffer, priority will be assigned threads on TLAB. In rare cases it may be directly assigned to the old era, not 100% fixed allocation rules, the details depend on the current use of which is to set the garbage collector combination, as well as virtual machines in memory-related parameters .

Next, we will explain a few of the most common memory allocation rules and to verify the code by those rules.

Objects priority allocation in Eden
most cases, the object allocation in the new generation of Eden area. When the Eden area is not enough space allocated, the virtual machine will launch a Minor GC.

Virtual machines provide -XX: PrintGCDetails the collector log parameters, print tell the virtual machine memory recovery log when garbage collection behavior, and the output current memory allocation in each region when the process exits. In actual application, the memory recovery log is generally print to a file for analysis by logging tool.

private static final int _1MB = 1024 * 1024;

/**
* VM参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
*/
public static void testAllocation() {
byte[] allocation1, allocation2, allocation3, allocation4;
allocation1 = new byte[2 * _1MB];
allocation2 = new byte[2 * _1MB];
allocation3 = new byte[2 * _1MB];
allocation4 = new byte[4 * _1MB]; // 出现一次Minor GC
}
运行结果:

 

testAllocation above code () method, and the size of 2MB 3 attempts a 4MB allocation size object at runtime -XMs20M, -XMx20M, -Xmn10M three parameters limit the Java heap size 20MB, can not be extended, which is assigned to the new generation of 10MB, 10MB allocated to the rest of the old era. -XX: SurvivorRatio = 9 determines the ratio of the space in the new generation area and a Survivor Eden zone is 8: 1, from the results of the output can clearly see the "eden space 8192K, from space 1024K, to space 1024K" information , the total available space for the new generation 9216KB (total capacity Eden region +1 Survivor region).

Occurs when the statement is executed assignment allocation4 object testAllocation () once Minor GC, GC is the result into a new generation of 6651KB 148KB, while the total memory footprint and almost no decrease (because allocation1, allocation2, allocation3 three objects is alive, the virtual machine is almost no recycled found objects). The reason this happens is to allocation4 GC allocates memory when i, found that Eden has been occupied 6MV, the remaining space is not sufficient to allocate 4MB of memory required allocation4, therefore Minor GC occurs. GC also found during the virtual machine has three 2MB size does not fit all objects space Survivor (Survivor space is only 1MB size), so I had to transfer by allocating guarantee mechanism to advance to the old year go.

After the end of the GC, allocation4 objects 4MB smooth distribution in Eden, so the result of program execution is completed Eden occupies 4MB (allocation4 is occupied), Survivor idle, the old year is occupied (by allocation1, allocation2, allocation3 occupancy). By GC logs can confirm this.

Note: Minor GC and repeatedly referred to the Full GC What is different?

New Generation GC (Minor GC): refers to the place in the new generation garbage collection action, because most of Java objects have properties Chaosheng evening off, so Minor GC very frequently, usually recover relatively fast speed.
Old's GC (Major GC / Full GC) : GC refers to occur in old age, there was Major GC, often accompanied by at least one of the Minor GC (but not absolute, it is directly in the collection policy Parallel Scavenge collector's Major GC conduct of policy selection process). Major GC generally slower than the speed of more than 10 times Minor GC.
Large objects directly into old's
so-called large object refers to a Java object requires a lot of contiguous memory space, the most typical is the kind of large objects and long strings array (byte [] array is typical of large objects). Large object on the memory allocation for virtual machines is a bad news (for the Java Virtual Machine complain the way, encountered a large object more than the bad news is met a group of "students toward evening off" and "short-lived large object", written procedures the time should be avoided), often easily lead to large objects ahead of garbage collection is triggered when there are a lot of memory space in order to obtain enough contiguous space, "placement" them.

Virtual machines provide a -XX: PretenureSizeThreshold parameters, so that the object is larger than the set value allocated directly in the old era. The aim is to avoid large amounts of memory copy (copy algorithm using the new generation of collecting memory) occurred in the area between Eden and two Survivor areas.

Final static int _1MB = Private 1024 1024 *;

/ **
* the VM parameters: -verbose: GC -Xms20M -Xmx20M -Xmn10M -XX: + PrintGCDetails -XX: =. 8 SurvivorRatio
* -XX: PretenureSizeThreshold = 3145728
* /
public static void testPretenureSizeThreshold () {
byte [] allocation;
allocation = new new byte [* _1MB. 4]; // allocated directly in the old era
}
implementation of the results:

 

After executing the above code testPretenureSizeThreshold () method, we see little Eden space is not used, and old age 10MB of space being used by 40%, which is the allocation of objects directly allocated in 4MB years old, this is because PretenureSizeThreshold is set to 3MB (is 3145728, this parameter can not be like -Xmx parameters such as direct write 3MB), 3MB thus exceeding the target will be directly allocated in the old era. Note PretenureSizeThreshold parameters only for Serial and ParNew two collector effective, Parallel Scavenge collector does not know this parameter, Parallel Scavenge collector generally does not need to set. If you encounter a situation you must use this parameter, consider a collector combination ParNew plus CMS.

Long-term survival of the object will enter the old years
since the idea of a virtual machine using generational collection to manage memory, the memory recovery must be able to identify which objects should be placed on the new generation, which objects should be placed in the old era. To do this, a virtual machine for each object defines a target age (Age) counter. If the object was born in Eden, and after the first Minor GC still alive, and can accommodate Survivor, it will be moved to Survivor space, and the object is set to 1. Survivor objects in every area "get through" a Minor GC, age, an increase of one-year-old, when his age to a certain extent (the default is 15 years old), they will be promoted to the old era. Object promoted's old age threshold, parameters can be -XX: MaxTenuringThreshold settings.

Final static int _1MB = Private 1024 1024 *;

/ **
* the VM parameters: -verbose: GC -Xms20M -Xmx20M -Xmn10M -XX: + PrintGCDetails -XX: SurvivorRatio = -XX. 8: MaxTenuringThreshold. 1 =
* -XX: + PrintTenuringDistribution
* /
@SuppressWarnings ( "unused")
public static void testTenuringThreshold () {
byte [] allocation1, allocation2, allocation3;
allocation1 = new new byte [_1MB / 4]; // when entering old's decision to XX: MaxTenuringThreshold set
allocation2 = byte new new [* _1MB. 4];
allocation3 = new new byte [* _1MB. 4];
allocation3 = null;
allocation3 = new new byte [* _1MB. 4];
}
in MaxTenuringThreshold = 1 parameter run results:

 

Try respectively -XX: MaxTenuringThreshold = 1 and -XX: MaxTenuringThreshold = 15 is provided to perform the above two kinds of code testTenuringThreshold () method, allocatioin1 this method requires the object memory 256KB, Survivor space can accommodate. After the time when MaxTenuringThreshold = 1, allocation1 years old when the object enters the second GC occurred, very clean become the new generation of post-GC memory has been used 0KB. And MaxTenuringThreshold = 15, the second GC occurred, allocation1 objects are Survivor remained in the new generation of space, then the new generation still has 404KB occupied.

Age Determination of dynamic objects
in order to better adapt to different conditions program memory, the virtual machine is not always the object of the requirements of the age reached MaxTenuringThreshold before promotion year old, the same age, if the sum is greater than the size of all the objects in space Survivor Survivor space half of the target age is greater than or equal to the age you can go directly years old, no need to wait until the age MaxTenuringThreshold in requirements.

private static final int _1MB = 1024 * 1024;

/**
* VM参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15
* -XX:+PrintTenuringDistribution
*/
@SuppressWarnings("unused")
public static void testTenuringThreshold2() {
byte[] allocation1, allocation2, allocation3, allocation4;
allocation1 = new byte[_1MB / 4]; // allocation1+allocation2大于survivo空间一半
allocation2 = new byte[_1MB / 4];
allocation3 = new byte[4 * _1MB];
allocation4 = new byte[4 * _1MB];
allocation4 = null;
allocation4 = new byte[4 * _1MB];
}
运行结果:

 

TestTenuringThreshold2 execute the above code () method, and set the -XX: MaxTenuringThreshold = 15, will find space occupied Survivor still operating results in 0%, while the old year increased by 6% higher than expected, that is to say, allocation1, allocation2 objects directly into the old era, and not wait until the 15-year-old critical age. Because these two objects together has reached 512KB, and they are of the same year, to meet the target to reach half of the same year rule Survivor space. We just need to comment out one of the objects the new operator, you will find another would not be promoted to the old year go.

Space allocation guarantees
before it happens Minor GC, virtual opportunity to check whether old's maximum available contiguous space is greater than all the objects in the new generation of total space, if this condition is met, then the Minor GC to ensure that it is safe. If not satisfied, the virtual opportunity to review whether to allow HandlePromotionFailure settings guarantee failure. If allowed, it will continue to check whether old's maximum available contiguous space larger than previous years old was promoted to the average size of the object, if greater than, will attempt to conduct a Minor GC, despite the Minor GC is risky; if less than, or HandlePromotionFailure settings do not allow risk, then it should be changed once a Full GC.

Below explain the "adventure" is to take any risk, mentioned earlier, using a new generation of copying collection algorithm, but for memory utilization, use only one Survivor space to rotate as a backup, so when a large number of objects in the Minor GC after the situation is still alive (the most extreme case is that the new generation of memory recall after all the objects have survived), you need to be allocated guarantee years old, can not accommodate the Survivor objects directly into the old era. And loan guarantees in life, similar to the old year to make such guarantees, provided that the remaining space itself, there's the old hold these objects, a total of how many objects will survive until the actual completion of garbage collection is not clearly known, so had once promoted to the average size of the recovery value of the object's capacity as the old experience, and the remaining space is compared to prior years old each take, Full GC to decide whether to make more space years old.

Compare fact still averaged a means of dynamic probability, that is, if the object after a sudden increase in survival time Minor GC, far higher than the average, it will still lead to a security failure (Handle Promotion Failure). If there is a HandlePromotionFailure failure, it had to re-initiate a Full GC after a failure. Although the circle around the time of the security failure is the largest, but in most cases are still open will HandlePromotionFailure switch, to avoid too frequent Full GC, you see the following code to run in the previous versions of JDK 6 Update 24 test.

private static final int _1MB = 1024 * 1024;

/**
* VM参数:-Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:-HandlePromotionFailure
*/
@SuppressWarnings("unused")
public static void testHandlePromotion() {
byte[] allocation1, allocation2, allocation3, allocation4, allocation5, allocation6, allocation7;
allocation1 = new byte[2 * _1MB];
allocation2 = new byte[2 * _1MB];
allocation3 = new byte[2 * _1MB];
allocation1 = null;
allocation4 = new byte[2 * _1MB];
allocation5 = new byte[2 * _1MB];
allocation6 = new byte[2 * _1MB];
allocation4 = null;
allocation5 = null;
allocation6 = null;
= new new byte allocation7 [2 * _1MB];
}
In HandlePromotionFailure = false parameter run results:

 

To HandlePromotionFailure = true parameter to run the results:

 

After JDK 6 Update 24, the test results will vary, HandlePromotionFailure parameter space will not affect the virtual machine allocation strategy guarantees, OpenJDK source code changes observed in (see the code below), although the source code also defines HandlePromotionFailure parameters, but already no longer use it in your code. Rule changes after 6 Update 24 JDK as long as the average size of the contiguous space old age is greater than the total size of the new generation of the object or the previous promotion will be Minor GC, otherwise it will be Full GC.

 

Guess you like

Origin www.cnblogs.com/hyhy904/p/10954423.html