Actual combat: memory allocation and recycling strategy

Posted by ManicMax on Mon, 27 Dec 2021 21:45:44 +0100

1. Objects are allocated in Eden first

In most cases, objects are allocated in the Cenozoic Eden district. When the Eden area does not have enough space for allocation, the virtual machine will initiate a Minor GC

Parameters:

-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8

Indicates that the Java heap is 20MB, 10MB, the new generation, 10MB old age, and the size ratio of an Eden to a Survivor in the new generation is 8:1

code:

public class JvmTest {
	
	private static final int _1MB = 1024*1024;
	

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		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];  //MinorGC occurs once
	}
	

}

When allocating allocation4, Eden has occupied 6MB, and the remaining 4MB is not enough. Therefore, minor gc occurs, and all three 2MB objects cannot be placed in the 1MB survival area, so they can only be transferred to the old age in advance through the allocation guarantee mechanism.

result

Heap
 PSYoungGen      total 9216K, used 7291K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 89% used [0x00000000ff600000,0x00000000ffd1efe8,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 10240K, used 4096K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  object space 10240K, 40% used [0x00000000fec00000,0x00000000ff000010,0x00000000ff600000)
 Metaspace       used 2624K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 279K, capacity 386K, committed 512K, reserved 1048576K

Unlike in the book, my garbage collector only puts two 2MB objects into OldGen

2 objects directly enter the elderly generation

The reason to avoid large objects in the Java virtual machine is that when allocating space, it is easy to trigger garbage collection in advance when there is still a lot of space in the memory. When copying objects, large objects require high replication overhead.

parameter

-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:PretenureSizeThreshold=3145728

Indicates that objects larger than 3MB will be put directly into the older generation (but only valid for Serial and ParNew)

code

public class JvmTest {
	
	private static final int _1MB = 1024*1024;
	

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		byte[] allocation4 = new byte[4* _1MB];  //MinorGC occurs once
	}
	

}

The long-term surviving objects will enter the elderly generation

parameter

-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=1 -XX:+PrintTenuringDistribution

Indicates that the age reaches 1 and becomes the elderly generation

-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 -XX:+PrintTenuringDistribution

It means that when the age reaches 15, it becomes the elderly generation

code

public class JvmTest {
	
	private static final int _1MB = 1024*1024;
	

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		byte[] allocation1,allocation2,allocation3;  //MinorGC occurs once
		allocation1 = new byte[_1MB / 4];
		allocation2 = new byte[_1MB * 4];
		allocation3 = new byte[_1MB * 4];
		allocation3 = null;
		allocation3 = new byte[_1MB * 4];
	}
	

}

However, my results are consistent because the parameters are not applicable to my current collector

4 dynamic object age determination

The parameter is consistent with the above value of 15. allocation1 and 2 add up to 512kb, which is greater than half of survivor. It is regarded as the elderly generation.

public class JvmTest {
	
	private static final int _1MB = 1024*1024;
	

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		byte[] allocation1,allocation2,allocation3,allocation4;  //MinorGC occurs once
		allocation1 = new byte[_1MB / 4];
		allocation2 = new byte[_1MB / 4];
		allocation3 = new byte[_1MB * 4];
		allocation4 = new byte[_1MB * 4];
		allocation4 = null;
		allocation4 = new byte[_1MB * 4];
	}
	

}

5 space allocation guarantee

In the old age, the maximum available continuous space is less than the average size of objects promoted to the old age, that is, the risky Minor GC

If it fails at this time, Full GC will be performed. Therefore, HandlePromotionFailure is set to avoid too frequent Full GC.

After JDK 6, the rule becomes that if the maximum available continuous space in the old age is less than the average size of objects promoted to the old age, Full GC is performed without setting.

parameter

-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:-HandlePromotionFailure

code

public class JvmTest {
	
	private static final int _1MB = 1024*1024;
	

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		byte[] allocation1,allocation2,allocation3,allocation4;  
		byte[] allocation5,allocation6,allocation7;
		allocation1 = new byte[_1MB * 2];
		allocation2 = new byte[_1MB * 2];
		allocation3 = new byte[_1MB * 2];
		allocation1 = null;
		allocation4 = new byte[_1MB * 2];
		allocation5 = new byte[_1MB * 2];
		allocation6 = new byte[_1MB * 2];
		allocation4 = null;
		allocation5 = null;
		allocation6 = null;
		
		allocation7 = new byte[_1MB * 2];
	}
	

}

Failed to run on my computer. HandlePromotionFailure is not recognized

Topics: Java jvm Back-end