天天看點

JVM 模拟對象進入老年代的四種情況

JVM 模拟對象進入老年代的四種情況

github

1、JVM參數設定

JVM參數設定(JDK1.8)
-XX:InitialHeapSize=20971520
-XX:MaxHeapSize=20971520
-XX:NewSize=10485760
-XX:MaxNewSize=10485760
-XX:SurvivorRatio=8/3
-XX:MaxTenuringThreshold=15/5
-XX:PretenureSizeThreshold=10485760/5242880
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:gc.log
           

2、模拟通過動态年齡判定規則進入老年代:如果Survivor區域 年齡1+...+年齡n 對象總和大于Survivor區域的50%,年齡n以上的對象會進入老年代。

2.1.Java代碼

public class GCDemo_02 {

	public static void main(String[] args) {
		/**
		 * 建立三個2M大小的數組
		 * 将array_1設定為null
		 */
		byte[] array_1 = new byte[2 * 1024 * 1024];
		array_1 = new byte[2 * 1024 * 1024];
		array_1 = new byte[2 * 1024 * 1024];
		array_1 = null;
		/**
		 * 建立一個128k大小的數組
		 */
		byte[] array_2 = new byte[128 * 1024];
		/**
		 * 建立一個2M大小的數組
		 * Eden區域記憶體不夠發生GC
		 */
		byte[] array_3 = new byte[2 * 1024 * 1024];
		/**
		 * 建立兩個2M大小的數組,一個128K大小的數組
		 * 将array_3設定為null
		 */
		array_3 = new byte[2 * 1024 * 1024];
		array_3 = new byte[2 * 1024 * 1024];
		array_3 = null;
		/**
		 * 建立一個2M大小的數組
		 * Eden區域記憶體不夠發生GC,GC過後的記憶體加上Survivor的記憶體大于Survivor記憶體的50%,将Survivor記憶體資料放入老年代
		 */
		byte[] array_4 = new byte[2 * 1024 * 1024];
	}
	
}
           

2.2.過程分析

1、新生代大小20M,Eden大小8M,from大小1M,to大小1M,JVM系統使用記憶體大小1M(GCDemo_00得知)。
2、第一次YoungGC
	1.建立三個2M的數組,然後将其設定為null,表示其可以被GC回收。
	2.建立一個128K的數組,這是通過動态年齡規則進入老年代的記憶體。
	3.此時Eden記憶體大小 3*2M + 1M + 128K = 7M 多一點。
	4.建立一個2M的數組,Eden記憶體不夠将觸發YoungGC。
3、第一次YoungGC後記憶體情況
	1.Eden區域有一個2M的數組(array_3)。
	2.from區域有一個128K的數組(array_2)和JVM系統使用的一部分記憶體一共677K,占比66%,超過了50%。
	3.Old區域為空。
4、第二次YoungGC
	1.建立兩個2M的數組,然後将其設定為null,表示其可以被GC回收。
	2.此時Eden記憶體大小 2M + 2M*2 + 1M = 7M 多一點。
	3.建立一個2M的數組,Eden記憶體不夠将觸發YoungGC。
5、第二次YoungGC後記憶體情況
	1.Eden區域有一個2M的數組(array_4)。
	2.from區域為空。根據動态年齡判定規則進入老年代。
	3.Old區域有一個128K的數組(array_2)和JVM系統使用的一部分記憶體一共677K。
           

3、模拟躲過指定年齡門檻值進入老年代

3.1.Java代碼

public class GCDemo_03 {

	public static void main(String[] args) {
		byte[] array_1 = new byte[2 * 1024 * 1024];
		array_1 = new byte[2 * 1024 * 1024];
		array_1 = null;
		
		byte[] array_2 = new byte[128 * 1024];
		
		byte[] array_3 = new byte[1 * 1024 * 1024];
		array_3 = new byte[1 * 1024 * 1024];
		array_3 = new byte[1 * 1024 * 1024];
		array_3 = new byte[1 * 1024 * 1024];
		array_3 = new byte[1 * 1024 * 1024];
		array_3 = null;
		
		byte[] array_4 = new byte[1024 * 1024];
		array_4 = new byte[1 * 1024 * 1024];
		array_4 = new byte[1 * 1024 * 1024];
		array_4 = new byte[1 * 1024 * 1024];
		array_4 = new byte[1 * 1024 * 1024];
		array_4 = null;
		
		byte[] array_5 = new byte[1 * 1024 * 1024];
		array_5 = new byte[1 * 1024 * 1024];
		array_5 = new byte[1 * 1024 * 1024];
		array_5 = new byte[1 * 1024 * 1024];
		array_5 = new byte[1 * 1024 * 1024];
		array_5 = null;

		byte[] array_6 = new byte[1 * 1024 * 1024];
		array_6 = new byte[1 * 1024 * 1024];
		array_6 = new byte[1 * 1024 * 1024];
		array_6 = new byte[1 * 1024 * 1024];
		array_6 = new byte[1 * 1024 * 1024];
		array_6 = null;
		
		
		byte[] array_7 = new byte[1 * 1024 * 1024];
		array_7 = new byte[1 * 1024 * 1024];
		array_7 = new byte[1 * 1024 * 1024];
		array_7 = new byte[1 * 1024 * 1024];
		array_7 = new byte[1 * 1024 * 1024];
		array_7 = null;
		
		byte[] array_8 = new byte[1 * 1024 * 1024];
	}
	
}
           

3.2.過程分析

1、新生代大小20M,Eden大小6M,from大小2M,to大小2M,JVM系統使用記憶體大小1M(GCDemo_00得知)。
2、第一次GC
	1.建立兩個2M的數組,然後将其設定為null,表示其可以被GC回收。
	2.建立一個128K的數組,這是躲過指定年齡門檻值進入老年代的對象。
	3.此時Eden記憶體大小 2*2M + 1M + 128K = 5M 多一點。
	4.建立一個1M的數組,Eden記憶體不夠将觸發YoungGC。
3、第二次GC
	1.建立4個1M的數組,然後将其設定為null,表示其可以被GC回收。
	2.此時Eden區域記憶體大小 4*1M + 1M = 5 M 多一點。
	4.建立一個1M的數組,Eden記憶體不夠将觸發YoungGC。
4、第三次GC。
5、第四次GC。
6、第五次GC。
7、第六次GC。此時128K的數組(array_2)和JVM系統使用的一部分記憶體一共677K躲過了指定年齡門檻值進入老年代。
           

4、模拟YoungGC過後對象因為放不下Survivor區域直接進入老年代

4.1.Java代碼

public class GCDemo_04 {

	public static void main(String[] args) {
		byte[] array_1 = new byte[2 * 1024 * 1024];
		array_1 = new byte[2 * 1024 * 1024];
		array_1 = new byte[2 * 1024 * 1024];
		
		byte[] array_2 = new byte[128 * 1024];
		array_2 = null;
		
		byte[] array_3 = new byte[2 * 1024 * 1024];
	}
	
}
           

4.2.過程分析

1、新生代大小20M,Eden大小8M,from大小1M,to大小1M,JVM系統使用記憶體大小1M(GCDemo_00得知)。
2、第一次GC
	1.建立三個2M的數組,讓後讓array_1指向第三個數組,表示前兩個數組可以被GC回收。
	2.建立一個128的數組,将其設定為null。
	3.此時Eden記憶體大小 2*3M + 1M + 128K = 7M 多一點。
	4.建立一個2M的數組,Eden記憶體不夠将觸發YoungGC。
3、第一次GC後記憶體情況
	1.Eden區域一個2M的數組(array_3)。
	2.from區域是JVM系統使用的一部分記憶體。
	3.Old區域一個2M的數組(array_1)。
           

5、模拟大對象直接進入老年代

5.1.Java代碼

public class GCDemo_05 {

	public static void main(String[] args) {
		byte[] array_2 = new byte[5 * 1024 * 1024];
	}
	
}