阅读前提:了解JVM内存模型。
Minor GC
: 对新生代进行垃圾回收,速度快。
Full GC
: 对整个堆进行垃圾回收。
Minor GC过程
创建大对象,通过参数PretenureSizeThreshold设置大对象标准,大对象直接存入老年代。创建小对象,小对象存储在Eden区。
新生代一般采用复制算法。当Eden区满时进行Minor GC,将Eden Space 和From Space中存活的对象复制到To Space,从Eden到To Space的对象设置年龄为1, 从From Space到To Space的对象年龄加一,清空Eden Space 和 From Space,当前的FromSpace作为下一次的To Space,当前的ToSpace作为下一次的From Space。当对象的年龄达到-XX:MaxTenuringThreshold指定的值后,将对象转存到老年代。当To Space中年龄相同的对象占To Space空间大小的一半以上时,大于等于该年龄的对象转存到老年代。当Eden Space 和From Space中存活的对象太多,To Space 无法装下时转存到老年代。
空间担保
进行Minor GC前,jvm会判断老年代的剩余空间是否大于Eden区的对象总和,若大于则此次进行Minor GC是安全的,因为即使Eden区全部对象都存活,也能存放在老年代。若小于,则看参数HandlePromotionFailure。若HandlePromotionFailure为false,则进行Full GC。当为true时,判断历次Minor GC后进入老年代的平均大小是否大于老年代的剩余空间。若大于,进行Full GC,否则进行Minor GC,但是有风险,尝试Minor GC发现存活对象过多以致老年代也无法装下,则升级为Full GC。
Minor GC、Full GC的触发条件
Minor GC
: Eden区满
Full GC
:
- 方法区是永久代实现的话,永久代空间不足
- 老年代的剩余空间小于Eden区的对象总和且HandlePromotionFailure为false
- 老年代的剩余空间小于Eden区的对象总和,HandlePromotionFailure为true,历次Minor GC后进入老年代的平均大小大于老年代的剩余空间
- 尝试Minor GC发现存活对象过多以致老年代也无法装下
- System.gc 建议执行Full GC,但不一定执行
- heap dump,生成堆转储文件时会先full gc
进入老年代的情况
- 创建大对象,通过参数PretenureSizeThreshold设置大对象标准,大对象直接存入老年代
- 当对象的年龄达到-XX:MaxTenuringThreshold指定的值后,将对象转存到老年代。
- 当To Space中年龄相同的对象占To Space空间大小的一半以上时,大于等于该年龄的对象转存到老年代。
- 当Eden Space 和From Space中存活的对象太多,To Space 无法装下时转存到老年代。