JVM空间分配担保(失败担保机制)
在发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间。如果这个条件成立,那么Minor GC可以确保是安全的。如果不成立,则虚拟机会查看HandlerPromotionFailure设置是否允许担保失败。如果允许,那么会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小。如果大于,将尝试着进行一次Monitor GC,尽管这次GC是有风
在发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间。如果这个条件成立,那么Minor GC可以确保是安全的。如果不成立,则虚拟机会查看HandlerPromotionFailure设置是否允许担保失败。如果允许,那么会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小。如果大于,将尝试着进行一次Monitor GC,尽管这次GC是有风险的。如果小于,或者HandlerPromotionFailure设置不允许冒险,那这时也要改为进行一次Full GC了。
上述所说的冒险到底是冒的什么险呢?
前面提到过,新生代使用复制收集算法,但是为了内存利用率。只使用其中一个Survivor空间来作为轮换备份,因此当出现大量对象在Minor GC后仍然存活的情况(最极端的情况是内存回收之后,新生代中所有的对象都存活),就需要老年代进行分配担保,把Survivor无法容纳的对象直接进入老年代。老年代要进行这样的担保,前提是老年代本身还有容纳这些对象的剩余空间,一共有多少对象存活下来在实际完成内存回收之前是无法明确知道的,所以只好取之前每一次回收晋升到老年代对象容量的平均大小值作为经验值,与老年代的剩余空间进行比较,决定是否进行Full GC来让老年代腾出更多空间。
取平均值进行比较其实仍然是一种动态概率的手段,也就是说,如果某次Minor GC存活后的对象突增,远远高于平均值的话,依然会导致担保失败。如果出现HandlerPromotionFailure失败,那就只好在失败后重新发起一次FULL GC。虽然担保失败时绕的圈子是最大的,但大部分情况下都还是将HandlerPromotionFailure开关打开,避免Full GC过于频繁。
更多推荐
所有评论(0)