回答
1、大对象直接进入老年代
为了避免一些大对象在 Eden 区和 Survivor 区频繁地复制,JVM 会直接将这些大对象分配到老年代。那多大的对象才是大对象呢?可以通过 -XX:PretenureSizeThreshold
控制,超过这个大小的对象直接进入老年代。
2、对象在年轻代经历多次 GC 后仍然存活
年轻代分为三个区:Eden区、Survivor 0
区和Survivor 1
区,新建对象直接在 Eden 区分配。当 Eden 区满了后,JVM 会触发一次 Minor GC
,存活的对象会被复制到 Survivor 0
区。当下次触发 Minor GC
时,JVM 会将存活的对象复制到 Survivor 1
。若一个对象经历多次(默认 15 次) Minor GC
后仍然存活,那么该对象会被晋升到老年代。
3、动态年龄判断
并不是所有的对象都需要经历 15 次 Minor GC
才会进入老年代。JVM 有一个动态年龄判断机制,即若在 Survivor 空间中相同年龄所有对象大小的总和大于 Survivor 空间的一半,则年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到 MaxTenuringThreshold
中要求的年龄。
4、Minor GC 后,Survivor 放不下的对象
Minor GC
后,需要将存活的对象复制到空闲的 Survivor
区,如果该 Survivor
的大小不足以容纳所有的存活对象,则 JVM 会将一部分对象直接放入到老年代,若老年代的空间也不够,则会触发 Full GC
。