Home  >  Article  >  Java  >  A brief discussion on java memory allocation and recycling strategies

A brief discussion on java memory allocation and recycling strategies

巴扎黑
巴扎黑Original
2017-06-26 10:41:411124browse

1. Introduction

The automatic memory management mentioned in the Java technology system is ultimately two issues: memory allocation and recycling. I have talked to you about the relevant knowledge of Java recycling before, and I will talk to you today. Let’s talk about the allocation of java objects in memory. In layman's terms, the memory allocation of objects is the allocation on the heap. The objects are mainly allocated on Eden of the new generation (the generation of objects in memory will be supplemented during garbage collection. If you want to know more, you can also refer to "In-depth Understanding" Java Virtual Machine"), if the local thread allocation buffer is started, it will be allocated on the TLAB according to thread priority. In a few cases, it is also allocated directly in the old generation.

2. Classic allocation strategy

1. Objects are allocated on Eden first

Under normal circumstances, objects are allocated on Eden first. When Eden does not have enough space, When allocating, the jvm will initiate a Minor GC. If there is still not enough space allocated, there are other measures later, which will be mentioned below.

Set the virtual machine's odd log parameter -XX:+PrintGCDetails. During garbage collection, the memory recycling log will be printed, and when the process exits, the current allocation of each memory area will be output. Let's look at a specific example. First, you need to set the jvm parameters -Xms20m -Xmx20m -Xmn10m. These three parameters indicate that the Java heap size is 20M and cannot be expanded. 10M is allocated to the new generation and the remaining 10M is allocated to the old generation. Era. -XX:SurvivorRatio=8 is the default ratio of Eden and Survivor in the new generation of jvm. The default is 8:1. The reason is that 98% of the objects in the new generation will be recycled during the next GC, so it is very suitable to use the copy algorithm for garbage collection. Therefore, of the 10M memory in the new generation, 8M is Eden, 1M is Survivor, and the other 1M is unused. The memory block that cooperates with the copy algorithm is also a Survivor.

 1 public class ReflectTest { 2  3     private static final int _1MB = 1024*1024; 4      5     public static void testAllocation(){ 6         byte[] allocation1 , allocation2 , allocation3 , allocation4; 7         allocation1 = new byte[2 * _1MB]; 8         allocation2 = new byte[2 * _1MB]; 9         allocation3 = new byte[2 * _1MB];10         allocation4 = new byte[6 * _1MB];11     }12     13     public static void main(String[] args) {14         ReflectTest.testAllocation();15     }16     17 }

The output is as follows

Heap
 PSYoungGen      total 9216K, used 6651K [0x000000000b520000, 0x000000000bf20000, 0x000000000bf20000)
  eden space 8192K, 81% used [0x000000000b520000,0x000000000bb9ef28,0x000000000bd20000)
  from space 1024K, 0% used [0x000000000be20000,0x000000000be20000,0x000000000bf20000)
  to   space 1024K, 0% used [0x000000000bd20000,0x000000000bd20000,0x000000000be20000)
 PSOldGen        total 10240K, used 6144K [0x000000000ab20000, 0x000000000b520000, 0x000000000b520000)
  object space 10240K, 60% used [0x000000000ab20000,0x000000000b120018,0x000000000b520000)
 PSPermGen       total 21248K, used 2973K [0x0000000005720000, 0x0000000006be0000, 0x000000000ab20000)
  object space 21248K, 13% used [0x0000000005720000,0x0000000005a07498,0x0000000006be0000)

You can see that eden occupies 81%, indicating that allocation1, allocation2, and allocation3 are all allocated in the new generation Eden superior.

2. Large objects are directly allocated in the old generation

Large objects refer to objects that require a large amount of continuous memory space to store, similar to long strings and arrays. Large objects are not a good thing for the memory distribution of the virtual machine. It is more difficult for the JVM to handle many large objects that only survive for one round. Such problems should be avoided when writing code. The -XX:PretenureSizeThreshold parameter is provided in the virtual machine. Objects larger than this value are directly allocated to the old generation. The purpose of this is to avoid a large amount of memory copy between the Eden area and the Survivor area. The garbage mentioned before The recycling algorithm and copying algorithm have been mentioned before, so I won’t go into details.

public class ReflectTestBig {private static final int _1MB = 1024*1024;    public static void testAllocation(){byte[] allocation2 , allocation3 , allocation4;allocation2 = new byte[2 * _1MB];
        allocation3 = new byte[2 * _1MB];
        allocation4 = new byte[6 * _1MB];
    }    public static void main(String[] args) {
        ReflectTestBig.testAllocation();
    }
    
}

The output is as follows

Heap
 PSYoungGen      total 8960K, used 4597K [0x000000000b510000, 0x000000000bf10000, 0x000000000bf10000)
  eden space 7680K, 59% used [0x000000000b510000,0x000000000b98d458,0x000000000bc90000)
  from space 1280K, 0% used [0x000000000bdd0000,0x000000000bdd0000,0x000000000bf10000)
  to   space 1280K, 0% used [0x000000000bc90000,0x000000000bc90000,0x000000000bdd0000)
 PSOldGen        total 10240K, used 6144K [0x000000000ab10000, 0x000000000b510000, 0x000000000b510000)
  object space 10240K, 60% used [0x000000000ab10000,0x000000000b110018,0x000000000b510000)
 PSPermGen       total 21248K, used 2973K [0x0000000005710000, 0x0000000006bd0000, 0x000000000ab10000)
  object space 21248K, 13% used [0x0000000005710000,0x00000000059f7460,0x0000000006bd0000)

You can see that allocation4 has exceeded the set -XX:PretenureSizeThreshold=3145728, and allocation4 is directly allocated to In the old generation, the occupancy rate of the old generation is 60%. Note that the setting -XX:PretenureSizeThreshold=3145728 cannot be written as -XX:PretenureSizeThreshold=3m, otherwise the jvm will not be recognized.

3. Long-term surviving objects will enter the old generation

Since the virtual machine adopts the idea of ​​banded collection to manage memory, memory recycling must identify which objects should be placed in the new generation. Which objects should be placed in the old generation. In order to achieve this purpose, jvm defines an age counter (Age) for each object. If the object is born in Eden and survives the first Minor GC, and can be stored in the Survivor, it will be moved to the Survivor and the age of the object will be set to 1. Every time an object escapes Minor GC, its age will be increased by 1. When its age exceeds the threshold of one year, the object will be promoted to the old generation. This threshold jvm defaults to 15 and can be set by -XX:MaxTenuringThreshold.

   m = 1024 * 1024  [] a1 =  [1 * m / 4[] a2 =  [7 *[] a3 =  [3 * m];

The output is as follows

[GC [DefNew: 7767K->403K(9216K), 0.0062209 secs] 7767K->7571K(19456K), 0.0062482 secs]   
[Times: user=0.00 sys=0.00, real=0.01 secs]   
a3 ok  
Heap  
 def new generation   total 9216K, used 3639K [0x331d0000, 0x33bd0000, 0x33bd0000)  
  eden space 8192K,  39% used [0x331d0000, 0x334f9040, 0x339d0000)  
  from space 1024K,  39% used [0x33ad0000, 0x33b34de8, 0x33bd0000)  
  to   space 1024K,   0% used [0x339d0000, 0x339d0000, 0x33ad0000)  
 tenured generation   total 10240K, used 7168K [0x33bd0000, 0x345d0000, 0x345d0000)  
   the space 10240K,  70% used [0x33bd0000, 0x342d0010, 0x342d0200, 0x345d0000)  
 compacting perm gen  total 12288K, used 381K [0x345d0000, 0x351d0000, 0x385d0000)  
   the space 12288K,   3% used [0x345d0000, 0x3462f548, 0x3462f600, 0x351d0000)  
    ro space 10240K,  55% used [0x385d0000, 0x38b51140, 0x38b51200, 0x38fd0000)  
    rw space 12288K,  55% used [0x38fd0000, 0x396744c8, 0x39674600, 0x39bd0000)

You can see that a2 has survived once, and its age is 1, which satisfies the set -XX:MaxTenuringThreshold=1, so a2 has entered the old generation, and a3 has entered the new generation.

4. Dynamic object age determination

In order to better adapt to the memory status of different programs, the virtual machine does not always require that the age of the object must reach the value set by -XX:MaxTenuringThreshold. In order to be promoted to the old age, if the sum of the sizes of all objects of the same age in the Survivor space is greater than half of the Survivor space, objects whose age is greater than or equal to this age can directly enter the old age without reaching the value set in -XX:MaxTenuringThreshold.

5. Space Allocation Guarantee

When Minor GC occurs, the virtual machine will detect whether the average size of each promotion to the old generation is greater than the remaining space of the old generation. If it is greater, proceed directly One FUll GC. If it is less than, check whether the HandlerPromotionFailyre setting allows guarantee failure. If it is allowed, only Minor GC will be performed. If it is not allowed, a FUll GC will also be improved. That is to say, when the new generation Eden cannot store the modified object, the object will be stored in the old generation.

3. Commonly used jvm parameter settings

1. -Xms: Initial heap size, default (MinHeapFreeRatio parameter can be adjusted) When the free heap memory is less than 40%, the JVM will increase the heap until -Maximum limit of Xmx.

2.

3. -Xmn: Young generation size (1.4or lator), the size here is (eden+ 2 survivor space). It is different from the New gen shown in jmap -heap.
The entire heap size = young generation size + old generation size + persistent generation size.
After increasing the young generation, the size of the old generation will be reduced. This value has a greater impact on system performance. Sun officially recommends a configuration of 3/8 of the entire heap.

4. -XX:NewSize: Set the young generation size (for 1.3/1.4).

5. -XX:MaxNewSize: The maximum value of the young generation (for 1.3/1.4).

6, -XX:PermSize: Set the initial value of the persistent generation (perm gen).

7, -XX:MaxPermSize: Set the maximum size of the persistent generation.

8. -Xss: The stack size of each thread. After JDK5.0, the stack size of each thread is 1M. In the past, the stack size of each thread was 256K. The memory size required by the application thread can be adjusted. .Under the same physical memory, reducing this value can generate more threads. However, the operating system still has limits on the number of threads in a process and cannot be generated infinitely. The experience value is around 3000~5000.

9, -XX:NewRatio: The ratio of the young generation (including Eden and two Survivor areas) to the old generation (excluding the persistent generation), -XX:NewRatio=4 indicates the difference between the young generation and the old generation The ratio value is 1:4, and the young generation accounts for 1/5 of the entire stack. When Xms=Xmx and Xmn is set, this parameter does not need to be set.

10. -XX:SurvivorRatio: The size ratio of the Eden area and the Survivor area is set to 8, then the ratio of two Survivor areas to one Eden area is 2:8, and one Survivor area accounts for the entire young generation. 1/10.

11. -XX:LargePageSizeInBytes: The size of the memory page cannot be set too large, which will affect the size of Perm.

12. -XX:+DisableExplicitGC: Close System.gc()

13. -XX:MaxTenuringThreshold: The maximum age of garbage. If set to 0, the young generation objects will not pass through Survivor area, directly enter the old generation. For applications with a large number of old generations, efficiency can be improved. If this value is set to a larger value, the young generation objects will be copied multiple times in the Survivor area, so that more objects can be added. The survival time of the young generation increases the probability of being recycled in the young generation. This parameter is only effective in serial GC.

14. -XX:PretenureSizeThreshold: If the object exceeds the size, it is allocated directly in the old generation. The unit byte is invalid when the new generation uses Parallel Scavenge GC. Another situation where it is allocated directly in the old generation is a large array. object, and there are no external reference objects in the array.

15. -XX:TLABWasteTargetPercent: The percentage of TLAB in the eden area.

4. Supplement

The difference between Minor GC and FUll GC:

New generation GC (Minor GC): refers to the garbage collection action that occurs in the new generation, because java objects Large logarithms cannot escape the first round of GC, so Minor GC is used frequently and the recovery speed is generally faster.

Old generation GC (FULL GC/Major GC): refers to the GC that occurs in the old generation. When Major GC appears, it is often accompanied by at least one Minor GC (but not absolutely, in the collection strategy of the ParallelScavenge collector) There is a direct selection process for Major GC). The speed of Major GC is generally more than 10 times slower than Minor GC.

The above is the detailed content of A brief discussion on java memory allocation and recycling strategies. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn