1. 程式人生 > >內存分配規則

內存分配規則

class min object 收集 log 連續 cde def null

對象優先在Eden分配

  大多數情況下,對象會在新生代Eden區中分配,當Eden區中沒有足夠空間時,虛擬機將發起一次Minor GC。  

package com.wjz.demo;

public class HeapOOM {
    static class OOMObject {}
    /**
     * 使用 Serial / Serial Old 組合收集器
     * -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+UseSerialGC
     * @param
args */ private static final int _1MB = 1024*1024; public static void main(String[] args) { byte[] b1, b2, b3, b4; b1 = new byte[2*_1MB]; b2 = new byte[2*_1MB]; b3 = new byte[2*_1MB]; b4 = new byte[4*_1MB]; // 此處會出現一次Minor GC } }

運行結果

[GC [DefNew: 6993K->554K(9216K), 0.0212177 secs] 6993K->6698K(19456K), 0.0318550 secs] [Times: user=0.00 sys=0.02, real=0.03 secs] 
Heap
 def 
new generation total 9216K, used 4978K [0x00000000f9a00000, 0x00000000fa400000, 0x00000000fa400000) eden space 8192K, 56% used [0x00000000f9a00000, 0x00000000f9e51fa0, 0x00000000fa200000) from space 1024K, 54% used [0x00000000fa300000, 0x00000000fa38a8b0, 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 2556K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000) the space 21248K, 12% used [0x00000000fae00000, 0x00000000fb07f258, 0x00000000fb07f400, 0x00000000fc2c0000) No shared spaces configured.

  eden space 8192K:新生代Eden區

  from space 1024K:新生代from survivor區

  to space 1024K:新生代to survivor區

  the space 10240K:老年代區

結果分析

  新生代內存占用量由6993K降到554K,總內存占用量由6993K升到6998K幾乎沒有變化。3個2M對象分配內存時放入了新生代Eden區,此時Eden區還剩2M左右的內存空間, 又來了一個4M對象想放進Eden區當時顯然不可能,觸發了一次Minor GC,復制算法開始將Eden區的對象復制到from survivor區,但是from survivor區只有1M空間,所以 只能將這3個2M對象通過分配擔保轉移到老年代中。4M對象被分配到了Eden區。

大對象直接進入老年代

  大對象是指需要大量連續空間的對象如字符串和數組。

package com.wjz.demo;

public class HeapOOM {
    static class OOMObject {}
    /**
     * 使用 Serial / Serial Old 收集器
     * -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+UseSerialGC 
     * -XX:PretenureSizeThreshold=3145728(僅Serial、PreNew有效)
     * @param args
     */
    private static final int _1MB = 1024*1024;
    public static void main(String[] args) {
        byte[] b1;
        b1 = new byte[4*_1MB];
    }
}

運行結果

Heap
 def new generation   total 9216K, used 1013K [0x00000000f9a00000, 0x00000000fa400000, 0x00000000fa400000)
  eden space 8192K,  12% used [0x00000000f9a00000, 0x00000000f9afd518, 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 2553K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
   the space 21248K,  12% used [0x00000000fae00000, 0x00000000fb07e5d8, 0x00000000fb07e600, 0x00000000fc2c0000)
No shared spaces configured.

結果分析

  新生代Eden和survivor區幾乎沒有使用,老年區占用了40%,因為大於3M的對象直接分配到了老年代中。

長期存活的對象進入老年代

  設置-XX:MaxTenuringThreshold參數設置對象進入老年代的年齡閾值。  

package com.wjz.demo;

public class HeapOOM {
    static class OOMObject {}
    /**
     * 使用 Serial / Serial Old 收集器
     * -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+UseSerialGC 
     * -XX:MaxTenuringThreshold=1 -XX:+PrintTenuringDistribution
     * @param args
     */
    private static final int _1MB = 1024*1024;
    public static void main(String[] args) {
        byte[] b1, b2, b3, b4;
        b1 = new byte[_1MB/4];
        b2 = new byte[4*_1MB];
        b3 = new byte[4*_1MB];
        b3 = null;
        b4 = new byte[4*_1MB];
    }
}

運行結果

[GC [DefNew
Desired survivor size 524288 bytes, new threshold 1 (max 1)
- age   1:     829632 bytes,     829632 total
: 5201K->810K(9216K), 0.0036339 secs] 5201K->4906K(19456K), 0.0036706 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:        256 bytes,        256 total
: 5234K->0K(9216K), 0.0013901 secs] 9330K->4906K(19456K), 0.0014093 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 def new generation   total 9216K, used 4260K [0x00000000f9a00000, 0x00000000fa400000, 0x00000000fa400000)
  eden space 8192K,  52% used [0x00000000f9a00000, 0x00000000f9e28fd0, 0x00000000fa200000)
  from space 1024K,   0% used [0x00000000fa200000, 0x00000000fa200100, 0x00000000fa300000)
  to   space 1024K,   0% used [0x00000000fa300000, 0x00000000fa300000, 0x00000000fa400000)
 tenured generation   total 10240K, used 4906K [0x00000000fa400000, 0x00000000fae00000, 0x00000000fae00000)
   the space 10240K,  47% used [0x00000000fa400000, 0x00000000fa8ca8d0, 0x00000000fa8caa00, 0x00000000fae00000)
 compacting perm gen  total 21248K, used 2556K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
   the space 21248K,  12% used [0x00000000fae00000, 0x00000000fb07f258, 0x00000000fb07f400, 0x00000000fc2c0000)
No shared spaces configured.

內存分配規則