概述
- 如果对象在Eden出生并经过第一次Minor GC后依然存活,并且能被Survivor容纳的话,将被移动到Survivor空间中,把那个将对象年龄设为1,对象在Survivor区中每熬过一次MinorGC,年龄就增加一岁,当它的年龄增加到一定程度(默认15岁,其实每个JVM、每个GC都有所不同)时,就会被晋升到老年代中
- 对象晋升老年代的年龄阈值,可以通过选项-XX:MaxTenuringThreshold来设置
- 针对不同年龄段的对象分配原则如下
- 优先分配到Eden
- 大对象直接分配到老年代,尽量避免程序中出现过多的大对象
- 长期存活的对象分配到老年代
- 动态对象年龄判断:如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入到老年代,无需等到MaxTenuringThreshold中要求的年龄
- 空间分配担保:-XX: HandlePromotionFailure
代码
/** 测试:分配60m堆空间,新生代 20m ,Eden 16m, s0 2m, s1 2m,buffer对象20m,Eden 区无法存放buffer, 直接晋升老年代 * -Xms60m -Xmx60m -XX:NewRatio=2 -XX:SurvivorRatio=8 -XX:+PrintGCDetails */ public class YoungOldAreaTest { // 新生代 20m ,Eden 16m, s0 2m, s1 2m // 老年代 40m public static void main(String[] args) { //Eden 区无法存放buffer 晋升老年代 byte[] buffer = new byte[1024 * 1024 * 20];//20m } }
小结
-
年轻代是对象的诞生、生长、消亡的区域,一个对象在这里产生、应用、最后被垃圾回收器收集、结束生命
-
老年代放置长生命周期对象,通常都是从Survivor区域筛选拷贝过来的Java对象。当然,也有特殊情况,我们知道普通的对象会被分配在TLAB上,如果对象较大,JVM会试图直接分配在Eden其他位置上;如果对象太大,完全无法在新生代找到足够长的连续空闲空间,JVM就会直接分配到老年代
-
当GC只发生在年轻代中,回收年轻对象的行为被称为MinorGC。当GC发生在老年代时则被称为MajorGC或者FullGC。一般的,MinorGC的发生频率要比MajorGC高很多,即老年代中垃圾回收发生的频率大大低于年轻代