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后: