關於這一段代碼 有幾個不是讓人很理解的地方,我一一說來。
1.Desired survivor size 524288 bytes
關於這個512KB空間是怎么來的,JVM有這樣一個參數:
-XX:TargetSurvivorRatio:目標存活率,默認為50%,表明所有age的survivor space對象的大小如果超過Desired survivor size,則重新計算threshold,以age和MaxTenuringThreshold的最小值為准,否則以MaxTenuringThreshold為准.
簡單的說,如果要分配的Survivor空間是1M那么,desired survivor size 就是512KB,這個大小影響的是Tenuring Threshold參數
當你試圖放入800KB的對象是,Survivor from是運行你放入的,但是Tenuring Threshold大小會變成1(就算你之前是15,這里也會動態改成1),即下次GC發生時,age=1的統統放入老年代
2.Eden,Survivor from,to的關系
對象分配空間的時候,若Eden仍有區域時,都會將對象放置Eden,持續新增對象一段時間后,Eden無法容納時,這個時候就會發生一次Minor GC。
當發生Minor GC時,會將Eden和 Survivor from中的幸存對象存放在Survivor to中,同時這些對象的age+1。
若Survivor to無法容納幸存對象,就將無法容納的對象放置在永久帶中。
當GC時,存在對象的age=Tenuring Threshold時,不管Survivor to是否空間足夠,都將他們放入永久代。
發生GC的前提,放入對象時空間不夠,放入對象后空間占用完畢。
這段例子中,當XX:MaxTenuringThreshold=1時
a1 = 0.25M,a2=4M;
分配a3=4M時,Eden無法容納4M的對象了,發起Minor GC,此時a1,a2 age=1,
這個時候,Survivor最大容量1M,無法同時容納存活的4.5M a1,a2
虛擬機將4M的a2放入老年代,同時將0.25M的a1放入Survivor to中,此時空間分布Eden(0M),Survivor from(0.25M),Old(4M)
放入4M的a3,此時空間分布Eden(4M),Survivor from(0.25M),Old(4M)
a3=null;只是說明了a3無引用,但是數組空間仍然存在,只是提示jvm我下次可以被回收了
a3=4M,又分配了4M的空間,這個時候Eden 4+4=8M 已經滿了,觸發一次GC(這時,jvm會清理age=1的對象,a1,a2被放在了老年代)
發現之前創建的4M數組沒有GC Root相關聯,而且不符合自救規則,回收。
此時空間分布Eden(4M),Survivor from(0M),Old(4.25M)
/** * VM參數:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=1 -XX:+PrintTenuringDistribution * */ @SuppressWarnings("unused") public static void testTenuringThreshold() { byte[] allocation1, allocation2, allocation3; allocation1 = new byte[_1MB / 4]; //262144 什么時候進入老年代決定於XX:MaxTenuringThreshold設置 allocation2 = new byte[4 * _1MB]; //4194304 allocation3 = new byte[4 * _1MB]; allocation3 = null; allocation3 = new byte[4 * _1MB]; /** * * XX:MaxTenuringThreshold=1 [GC [DefNew Desired survivor size 524288 bytes, new threshold 1 (max 1) - age 1: 418144 bytes, 418144 total : 4695K->408K(9216K), 0.0054252 secs] 4695K->4504K(19456K), 0.0054708 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] [GC [DefNew Desired survivor size 524288 bytes, new threshold 1 (max 1) - age 1: 136 bytes, 136 total : 4668K->0K(9216K), 0.0013601 secs] 8764K->4504K(19456K), 0.0013867 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] Heap def new generation total 9216K, used 4260K [0x32750000, 0x33150000, 0x33150000) eden space 8192K, 52% used [0x32750000, 0x32b78fe0, 0x32f50000) from space 1024K, 0% used [0x32f50000, 0x32f50088, 0x33050000) to space 1024K, 0% used [0x33050000, 0x33050000, 0x33150000) tenured generation total 10240K, used 4504K [0x33150000, 0x33b50000, 0x33b50000) the space 10240K, 43% used [0x33150000, 0x335b60a0, 0x335b6200, 0x33b50000) compacting perm gen total 12288K, used 377K [0x33b50000, 0x34750000, 0x37b50000) the space 12288K, 3% used [0x33b50000, 0x33bae5c0, 0x33bae600, 0x34750000) ro space 10240K, 55% used [0x37b50000, 0x380d1140, 0x380d1200, 0x38550000) rw space 12288K, 55% used [0x38550000, 0x38bf44c8, 0x38bf4600, 0x39150000) */ }
這段例子中,當XX:MaxTenuringThreshold=8時
a1 = 0.25M,a2=4M;
分配a3=4M時,Eden無法容納4M的對象了,發起Minor GC
這個時候,Survivor最大容量1M,無法同時容納存活的4.5M a1,a2
虛擬將4M的a2放入老年代,同時將0.25M的a1放入Survivor to中,此時空間分布Eden(0M),Survivor from(0.25M),Old(4M)
放入3M的a3,此時空間分布Eden(4M),Survivor from(0.25M),Old(4M)
a3=null;只是說明了a3無引用,但是數組空間仍然存在,只是提示jvm我下次可以被回收了
a3=4M,又分配了4M的空間,這個時候Eden 4+4=8M 已經滿了,觸發一次GC
發現之前創建的4M數組沒有GC Root相關聯,而且不符合自救規則,回收。
此時空間分布Eden(4M),Survivor from(0.25M),Old(4M)
/** * * XX:MaxTenuringThreshold =8 [GC [DefNew Desired survivor size 524288 bytes, new threshold 8 (max 8) - age 1: 418144 bytes, 418144 total : 4695K->408K(9216K), 0.0036693 secs] 4695K->4504K(19456K), 0.0036983 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC [DefNew Desired survivor size 524288 bytes, new threshold 8 (max 8) - age 1: 136 bytes, 136 total - age 2: 417936 bytes, 418072 total : 4668K->408K(9216K), 0.0010034 secs] 8764K->4504K(19456K), 0.0010296 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] Heap def new generation total 9216K, used 4668K [0x32750000, 0x33150000, 0x33150000) eden space 8192K, 52% used [0x32750000, 0x32b78fe0, 0x32f50000) from space 1024K, 39% used [0x32f50000, 0x32fb6118, 0x33050000) to space 1024K, 0% used [0x33050000, 0x33050000, 0x33150000) tenured generation total 10240K, used 4096K [0x33150000, 0x33b50000, 0x33b50000) the space 10240K, 40% used [0x33150000, 0x33550010, 0x33550200, 0x33b50000) compacting perm gen total 12288K, used 377K [0x33b50000, 0x34750000, 0x37b50000) the space 12288K, 3% used [0x33b50000, 0x33bae5b8, 0x33bae600, 0x34750000) ro space 10240K, 55% used [0x37b50000, 0x380d1140, 0x380d1200, 0x38550000) rw space 12288K, 55% used [0x38550000, 0x38bf44c8, 0x38bf4600, 0x39150000) */