深入理解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后:

猜你喜欢

转载自blog.csdn.net/qq_33283652/article/details/84549912