对象最初都诞生在伊甸园,这些对象通常寿命都很短,在伊甸园空间不足,会触发年轻代回收,还活着的对象进入幸存区 S0,年轻代回收适合采用标记-复制算法
接下来再触发年轻代回收时,会将伊甸园和 S0 仍活着的对象复制到 S1,清空 S0,交换 S0 和 S1 职责经过多次回收仍不死的对象,会晋升至老年代,老年代适合放那些长时间存活的对象老年代回收如果满了,会触发老年代垃圾回收,会采用标记-整理或标记-清除算法。老年代回收时的暂停时间通常比年轻代回收更长
还会常问
晋升条件
,注意不同垃圾回收器,晋升条件不一样
在 parallel 里,经历 15 次(默认值)新生代回收不死的对象,会晋升可以通过 -XX:MaxTenuringThreshold 来调整
例外:如果幸存区中的某个年龄对象空间占比已经超过 50%,那么大于等于这个年龄的对象会提前晋升大对象的处理
首先大对象不适合存储在年轻代,因为年轻代是复制算法,对象移动成本高
,注意不同垃圾回收器,大对象处理方式也不一样
·在 serial 和 cms 里,如果对象大小超过阈值,会直接把大对象晋升到老年代这个國值通过 -XX:PretenureSizeThreshold 来设置
·在 g1 里,如果对象被认定为巨型对象(对象大小超过了region 的一半),会存储在巨型对象区
日Region 大小是堆内存总大小/2048(必须取整为2的幕),或者通过-XX:G1HeapRegionSize 来设置
PS.
著名教材《深入理解Java虚拟机》一书关于这些论述,很多观点陈旧过时,需要带批判眼光来学习。例如在它的《内存分配与回收策略》这一章节,提到了这些:
对象优先在Eden分配(OK)
大对象直接进入老年代(没有提到 g1 情况)
长期存活的对象将进入老年代(即我上面讲的晋开条件,但没强调要区分垃圾回收器)
动态对象年龄判定(即提前晋升)
空间分配担保(已过时)文中提到的-XX:+HandlePromotionFailure 参数在 jdk8 之后已经没了