jvm系列五:垃圾回收机制之对象进入老年代时机

1、前文回顾
上一篇文章(jvm垃圾回收机制之新生代垃圾回收算法)主要介绍了新生代垃圾回收算法——复制算法 。 我们简单回顾一下 , 当我们新创建的对象就会进入新生代中的Eden区 , 一开始 , S0区和S1区都是为空的 , 随着系统的运行 , 创建越来越多的对象 , 直到Eden区内存空间不足了 , 就会引发Young GC , 经过垃圾回收后 , 存活的对象迁移到S0区 , 然后Eden区清空掉 , 腾出内存空间 。 系统继续运行着 , 新创建的对象依旧放在Eden区 , 过了一段时间后 , 发现Eden区的空间又满了 , 又引发了Young GC , 这次垃圾回收会回收Eden和S0区 , 然后将这两个区剩余的存活的对象迁移到S1区 , 然后清空Eden区和S0区 , 如此反复 。 这个就是我们新生代垃圾回收算法 。
2、Young GC后存活对象大于survivor区内存空间
上面我们简单回顾了新生代的垃圾回收算法的过程 , 其实 , 只要你思考下就会发现有疑问 , 因为我们默认的Eden:S0:S1=8:1:1 , 假如我们新生代分配了1G , 那么Eden=0.8G , S0=S1=0.1G , 好的 , 那这样问题就来了 , 如果经过垃圾回收后 , 发现我们现在存活的对象还有0.2G , 但是我survivor区只有0.1G啊 , 我0.2G的存活对象怎么放得进去?是的 , 答案就是这0.2G的存活对象会进入老年代 。 这就是我们对象进入老年代的一个时机 , 简而言之 , 就是当经过垃圾回收后 , 存活的对象大于survivor区内存空间的时候 , 这些存活的对象就会进入老年代 。 如下图:
jvm系列五:垃圾回收机制之对象进入老年代时机文章插图
3、躲过垃圾回收15次之后进入老年代
我们都知道 , 在经过Young GC后 , 会留下一些存活对象 , 比如对象A是存活对象 , 那么经过一次Young GC后 , 它还存活着 , 那么对象A的年龄就加1 , 如果经过15次的垃圾回收 , 对象A依然还活着 , 那么它的年龄就会达到15 , 这个时候 , 对象A就会进入老年代 。 如下图:
jvm系列五:垃圾回收机制之对象进入老年代时机文章插图
4、大对象直接进入老年代
我们jvm中有一个参数“-XX:PretenureSizeThreshold” , 可以设置大对象的大小 , 比如我设置为1m , 当一个对象大于1m的时候 , 那么这个对象不会经过新生代 , 直接就进入老年代了 。 那为什么要这么规定呢?我们想想 , 如果还是遵循躲过垃圾回收15次进入老年代的原则 , 那就意味着这个大对象要在新生代来回复制 , 耗费时间 。 如下图:
jvm系列五:垃圾回收机制之对象进入老年代时机文章插图
5、动态对象年龄判断规则
所谓动态对象年龄判断规则 , 在survivor区中年龄1+年龄2+年龄3+...+年龄n的对象总和大于这个survivor区内存空间的一半 , 那么年龄n和n以上的对象就会进入老年代 。 比如 , 我们S1区内存是0.1G , 此时S1区中年龄1的对象0.01G , 年龄2的对象0.02G , 年龄3的对象0.03G , 年龄3的对象0.01G , 因为年龄1+年龄2+年龄3=0.01+0.02+0.03=0.06>0.1/2 , 所以这个时候年龄3和年龄4的对象就会进入老年代 。 如下图:
jvm系列五:垃圾回收机制之对象进入老年代时机文章插图
6、总结:
【jvm系列五:垃圾回收机制之对象进入老年代时机】好了 , 本文主要介绍了对象进入老年代的四个时机 , 分别是:Young GC后存活对象大于survivor区内存空间、躲过垃圾回收15次之后的对象进入老年代、大对象直接进入老年代、动态对象年龄判断规则 。 夜深了 , 暂时写到这里吧 , 下篇见 。


    推荐阅读