BiBi - JVM -6- 回收策略

From:深入理解Java虚拟机

  • 目录
    BiBi - JVM -0- 开篇
    BiBi - JVM -1- Java内存区域
    BiBi - JVM -2- 对象
    BiBi - JVM -3- 垃圾收集算法
    BiBi - JVM -4- HotSpot JVM
    BiBi - JVM -5- 垃圾回收器
    BiBi - JVM -6- 回收策略
    BiBi - JVM -7- Java类文件结构
    BiBi - JVM -8- 类加载机制
    BiBi - JVM -9- 类加载器
    BiBi - JVM -10- 虚拟机字节码
    BiBi - JVM -11- 编译期优化
    BiBi - JVM -12- 运行期优化
    BiBi - JVM -13- 并发

新生代GC称为:Minor GC
老年代GC称为:Major GC / Full GC
老年代GC时,通常会伴随至少一次新生代GC,但在Parallel Scavenge收集器的收集策略里就可以直进行老年代GC。

  • JVM回收小例子

描述:Java堆大小为20M,不可扩展,新生代占10M,老年代占10M。其中新生代Eden占8M,Survivor1和Survivor2分别占1M。生成对象a1【2M】、a2【2M】、a3【2M】、a4【4M】,当生成a4时会执行一次Minor GC。

过程:因为此时Eden + Survivor1 = 9M,a1 + a2 + a3 = 6M,剩下空间3M不够a4使用,所以采用复制算法,将a1、a2、a3复制到Survivor2中,但是Survivor2空间为1M,不足以保持任何一个对象,所以通过【分配担保机制】提前将a1、a2、a3转移到老年代中。最后a4分配在新生代的Eden中,Survivor1和Survivor2空闲,老年代被占用6M。

  • 大对象直接进入老年代

Serial和ParNew收集器通过PretenureSizeThreshold = 1024参数,可以令占用内存大于这个设置值的对象直接在老年代分配,这样做的目的:避免Eden和两个Survivor之间发生大量的复制操作

注意:Parallel Scavenge收集器没有这个参数。

  • 长期存活的对象将进入老年代

虚拟机给每个对象定义了一个对象年龄Age计数器,如果对象在Eden出生,经过Minor GC后仍然存活,并且能被Survivor容纳的话,将被移动到另一个Survivor空间中,对象的年龄设为1。对象在Survivor区中每熬过一次Minor GC,年龄就增加1,当增加到一定程度【默认为15岁】后晋升到老年代。

  • 动态对象年龄判断

如果Survivor空间中【相同年龄】的所有对象内存的总和大于Survivor空间的一半时,无需等待到达规定年龄,将年龄大于或等于该年龄的对象直接进入老年代。

  • 空间分配担保【即老年代分配担保的前提是:老年代能容纳将要进来的对象】

在发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果成立,那么Minor GC可以确定是安全的。如果不成立,虚拟机会查看HandlerPromotionFailure【冒险策略】设置值是否允许担保失败。如果允许,那么会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试一次Minor GC,尽管这次Minor GC是有风险的;如果小于,或者HandlePromotionFailure设置不允许冒险,那就会进行一次Full GC。

风险的含义:进行Minor GC会有多少对象会活下来,在实际完成内存回收之前是无法明确知道的,所以只好取之前每一次回收晋升到老年代对象容量的平均大小值作为经验值,与老年代的剩余空间进行比较。

你可能感兴趣的:(BiBi - JVM -6- 回收策略)