1. 程式人生 > >深入理解jvm(三、常用的垃圾收集規則)

深入理解jvm(三、常用的垃圾收集規則)

1.物件優先在Eden分配

Eden Space字面意思是伊甸園,物件被建立的時候首先放到這個區域,進行垃圾回收後,不能被回收的物件被放入到空的survivor區域。

Survivor Space倖存者區,用於儲存在eden space記憶體區域中經過垃圾回收後沒有被回收的物件。Survivor有兩個,分別為To Survivor、 From Survivor,這個兩個區域的空間大小是一樣的。執行垃圾回收的時候Eden區域不能被回收的物件被放入到空的survivor(也就是To Survivor,同時Eden區域的記憶體會在垃圾回收的過程中全部釋放),另一個survivor(即From Survivor)裡上次回收存在的不能被回收的物件也會被放入這個survivor(即To Survivor),然後To Survivor 和 From Survivor的標記會互換,始終保證一個survivor是空的。

新生代可用空間為Eden加To Survivor,老生代為From Survivor

-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8

-XX:SurvivorRatio=8決定新生代中的Eden區與一個 Survivor區的空間比例是8:1 

public class testAllocation {
    private static final int _1MB = 1024 * 1024;

    public static void main(String[] args) {
        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];
    }
}

2.大物件進入老年代 

 大物件:需要大量連續記憶體空間的Java物件,比如很長的字串或陣列。

-XX:PretenureSizeThreshold:大於這個設定值的物件直接在老年代分配。但該引數只對Serial和ParNew有效

-Xms20M -Xmx20M -Xmn10M -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:PretenureSizeThreshold=3145728
public class testAllocation {
    private static final int _1MB = 1024 * 1024;

    public static void main(String[] args) {
        byte[] allocation;
        allocation = new byte[4 * _1MB];
    }
}

3.長期存活的物件進入老年代

 虛擬機器給每個物件定義了一個物件年齡計數器。如果物件在Eden出生並經歷過一次Minor GC後仍然存活,並且能被Servivor容納的話,將被移動到Servivor空間中,並且物件年齡設為1。物件在Servivor去中每熬過一次Minor GC,年齡就增加一歲,當他的年齡增加到一定程度(預設為15)就將晉升為老年代。XX:MaxTenuringThreshold=1設定預設年齡為1。

-Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:MaxTenuringThreshold=1 
-XX:+PrintTenuringDistribution
public class testAllocation {
    private static final int _1MB = 1024 * 1024;

    @SuppressWarnings("unused")
    public static void main(String[] args) {
        byte[] allocation1, allocation2, allocation3;
        allocation1 = new byte[_1MB / 4];
        allocation2 = new byte[4 * _1MB];
        allocation3 = null;
        allocation3 = new byte[4 * _1MB];
    }
}

 4.動態物件年齡判定

如果在Servivor空間中年齡從小到大的累加和大於 Survivor空間的一半,年齡大於或等於該年齡的物件就可以直接進入老年代。

-Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -verbose:gc -XX:+UseSerialGC 
-XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 -XX:+PrintTenuringDistribution
public class testAllocation {
    private static final int _1MB = 1024 * 1024;

    @SuppressWarnings("unused")
    public static void main(String[] args) {
        byte[] allocation1, allocation2, allocation3,allocation4;
//        allocation1+allocation2大於Survivor空間的一半
        allocation1 = new byte[_1MB / 4];
        allocation2 = new byte[_1MB / 4];
        allocation3 = new byte[4 * _1MB];
        allocation4 = new byte[4 * _1MB];
        allocation4 = null;
        allocation4 = new byte[4 * _1MB];
    }
}

註釋掉allocation2後: