内存分配策略
堆内存区域被划分为1个Eden区、2个Survivor区(8:1:1)、一个Old区,GC流程如下:
- 在GC开始时,对象只存在Eden和From区,To区是空的
- Eden区中所有存活的对象都会被复制到To区
- From区存活的对象,会根据他们的年龄来决定去向,年龄到达默认15岁的对象会被移动到老年代中,没有到达15岁的对象会被复制到To区
- GC过后Eden和From区都已经被清空
- From区和To区互换角色
- Minor GC 一直重复这样的操作
对象年龄计算
如果对象在Eden区出生并经过第一次Minor GC后仍然存活并被Survivor区所接受,则被移动到Survivor区,并且对象年龄设为1,对象在Survivor中熬过一次Minor GC,年龄就增加1,直到年龄增加到15,就将会晋升到来年代中。晋升老年代的年龄阈值可以通过参数-XX:MaxTenuringThreshold设置。
动态对象年龄判定
为了更好的适应不同程序的内存情况, 虚拟机并不一定要求对象年龄到达MaxTenuringThreshold才能晋升老年代。如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄等于或大于该年龄的对象可以直接进入到老年代。
空间分配担保
在发生Minor GC之前,虚拟机会先检查老年代最大可用连续空间是否大于新生代所有对象总空间,如果这个条件成立,那么Minor GC可以确保是安全的,如果不成立,则虚拟机会查看HandlePromotionFailure设置值是否允许担保失败,如果允许,那么会继续检查老年代最大可用连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试进行一次Minor GC,尽管这次Minor GC有风险,如果小于,或者HandlePromotionFailure设置值不允许担保失败,那这时改为进行一次Full GC