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];
}
}