Java虛擬機(三):內存分配與回收策略

     對象的分配,就是在堆上,主要是新生代Eden區上分配對象空間,如果啓動了本地線程分配緩衝,將按照線程優先在TLAB上分配。少數情況下也可能分配在老年代中。
1、對象優先在Eden區分配
     大多數情況對象在新生代Eden區分配,當Eden區沒有足夠空間進行分配時,虛擬機將發起一次Minor GC。
     VM參數:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 。設置java堆大小限制爲20M,新生代10M,         Eden區和Survivor區的 比例是8,即Eden區爲8M,每個Survivor區大小爲1M,並打印垃圾回收日誌。
代碼:
package com.xl.jvm;
public class TestGc {
 
 private static final int _1MB = 1024 * 1024;
 /**
  * VM參數:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
   */
 public static void testAllocation() {
   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];  // 出現一次Minor GC
  }
 public static void main(String[] args) {
  testAllocation();
 }
}
結果:
[GC[DefNew: 6816K->474K(9216K), 0.0048603 secs] 6816K->6618K(19456K), 0.0049014 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
Heap
 def new generation   total 9216K, used 5062K [0x00000000f9a00000, 0x00000000fa400000, 0x00000000fa400000)
  eden space 8192K,  56% used [0x00000000f9a00000, 0x00000000f9e7af60, 0x00000000fa200000)
  from space 1024K,  46% used [0x00000000fa300000, 0x00000000fa376a28, 0x00000000fa400000)
  to   space 1024K,   0% used [0x00000000fa200000, 0x00000000fa200000, 0x00000000fa300000)
 tenured generation   total 10240K, used 6144K [0x00000000fa400000, 0x00000000fae00000, 0x00000000fae00000)
   the space 10240K,  60% used [0x00000000fa400000, 0x00000000faa00030, 0x00000000faa00200, 0x00000000fae00000)
 compacting perm gen  total 21248K, used 2461K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
   the space 21248K,  11% used [0x00000000fae00000, 0x00000000fb0675e8, 0x00000000fb067600, 0x00000000fc2c0000)
No shared spaces configured.
2、大對象直接進入老年代
     所謂大對象就是指需要大量連續內存空間的Java對象,最典型的大對象就是那種很長的字符串以及數組。這樣做的目的是避免Eden區及兩個Servivor之間發生大量的內存複製。
    VM參數:-XX:PretenureSizeThreshold=3145728 參數設定超過對象超過多少時,分配到老年代中,此例爲3M(3*1024*1024)。
代碼:
  
 package com.xl.jvm;

public class TestGc {
 
 private static final int _1MB = 1024 * 1024;
 /**
  * VM參數:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
  * -XX:PretenureSizeThreshold=3145728
  */
 public static void testPretenureSizeThreshold() {
  byte[] allocation;
  allocation = new byte[4 * _1MB];  //直接分配在老年代中
 }
 public static void main(String[] args) {
  testPretenureSizeThreshold();
 }
}

結果:
Heap
 def new generation   total 9216K, used 836K [0x00000000f9a00000, 0x00000000fa400000, 0x00000000fa400000)
  eden space 8192K,  10% used [0x00000000f9a00000, 0x00000000f9ad10d8, 0x00000000fa200000)
  from space 1024K,   0% used [0x00000000fa200000, 0x00000000fa200000, 0x00000000fa300000)
  to   space 1024K,   0% used [0x00000000fa300000, 0x00000000fa300000, 0x00000000fa400000)
 tenured generation   total 10240K, used 4096K [0x00000000fa400000, 0x00000000fae00000, 0x00000000fae00000)
   the space 10240K,  40% used [0x00000000fa400000, 0x00000000fa800010, 0x00000000fa800200, 0x00000000fae00000)
 compacting perm gen  total 21248K, used 2458K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
   the space 21248K,  11% used [0x00000000fae00000, 0x00000000fb066a70, 0x00000000fb066c00, 0x00000000fc2c0000)
No shared spaces configured.
3、長期存活的對象將進入老年代
     如果對象在Eden區出生並且盡力過一次Minor GC後仍然存活,並且能夠被Servivor容納,將被移動到Servivor空間中,並且把對象年齡設置成爲1.對象在Servivor區中每熬過一次Minor GC,年齡就增加1歲,當它的年齡增加到一定程度(默認15歲),就將會被晉級到老年代中。
   代碼:
package com.xl.jvm;
public class TestGc {
 private static final int _1MB = 1024 * 1024;
 /**
  * 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];  // 什麼時候進入老年代決定於XX:MaxTenuringThreshold設置
  allocation2 = new byte[4 * _1MB];
  allocation3 = new byte[4 * _1MB];
  allocation3 = null;
  allocation3 = new byte[4 * _1MB];
 }
 public static void main(String[] args) {
  testTenuringThreshold();
 }
}
結果:
[GC[DefNew
Desired survivor size 524288 bytes, new threshold 1 (max 1)
- age   1:     748104 bytes,     748104 total
: 5024K->730K(9216K), 0.0038710 secs] 5024K->4826K(19456K), 0.0039143 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC[DefNew
Desired survivor size 524288 bytes, new threshold 1 (max 1)
- age   1:        120 bytes,        120 total
: 4990K->0K(9216K), 0.0026329 secs] 9086K->4826K(19456K), 0.0026618 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
 def new generation   total 9216K, used 4424K [0x00000000f9a00000, 0x00000000fa400000, 0x00000000fa400000)
  eden space 8192K,  54% used [0x00000000f9a00000, 0x00000000f9e51f90, 0x00000000fa200000)
  from space 1024K,   0% used [0x00000000fa200000, 0x00000000fa200078, 0x00000000fa300000)
  to   space 1024K,   0% used [0x00000000fa300000, 0x00000000fa300000, 0x00000000fa400000)
 tenured generation   total 10240K, used 4826K [0x00000000fa400000, 0x00000000fae00000, 0x00000000fae00000)
   the space 10240K,  47% used [0x00000000fa400000, 0x00000000fa8b6a58, 0x00000000fa8b6c00, 0x00000000fae00000)
 compacting perm gen  total 21248K, used 2461K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
   the space 21248K,  11% used [0x00000000fae00000, 0x00000000fb0675d8, 0x00000000fb067600, 0x00000000fc2c0000)
No shared spaces configured.


參考資料:《深入理解Java虛擬機》

 


發佈了44 篇原創文章 · 獲贊 5 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章