美文网首页
JVM-动态年龄判断你真的理解了吗

JVM-动态年龄判断你真的理解了吗

作者: 别拿爱情当饭吃 | 来源:发表于2021-04-11 17:31 被阅读0次

    哈喽哈喽大家猴,我是把代码写成bug的大头菜。公众号:大头菜技术(bigheadit)。原创不易,但欢迎转载。

    看文章前,我们先复习一下。

    什么对象才能直接进入老年代?

    你可能很快就说出来,毕竟八股文不是白背的。

    • 大对象直接进入老年代。
    • 动态年龄判断
    • 年龄大于阈值,进入老年代
    • Minor GC后,存活的对象空间大于survivor空间,直接进入老年代。

    好了嘛,应该没了吧。

    这次,我们把目光聚焦到:动态年龄判断。

    下面这图片,摘自JVM书的一段话:

    JVM书籍-1.png

    什么时候对象能进入老年代空间时?

    其中一个触发条件就是:动态年龄判断。

    简单点说:在survivor中,相同年龄的所有对象大小大于survivor的一般空间。年龄大于或等于该年龄的对象可以进入老年代。

    但真的是这样子吗?

    前提条件:现在我假设survivor空间有100M空间。

    来。我举个例子哈,跟着我的思路走一遍。

    假设年龄3的对象大小超过了survivor区域的一半,比如占据60M吧。

    我们分析一下:年龄为3,说明经历了3次GC都存活了下来。

    然后我们思考一下,年龄3的对象是从哪里来的?

    肯定是从年龄2的对象中来的。这点毋庸置疑吧!

    我们再换个思路想一下。

    既然,年龄3的对象是从年龄2的对象中来的。(先说明哈:年龄,只增不减)

    现在年龄3的对象都已经超过survivor区域的一半了。

    那是不是可以说明:年龄2的对象也肯定超过survivor区域的一半。

    同理可得:年龄2的对象是从年龄1的对象中来的,那么年龄1的对象也肯定超过一半,是吧。这毋庸置疑吧!

    我们来复习一下:

    在survivor中,相同年龄的所有对象大小大于survivor的一般空间。年龄大于或等于该年龄的对象可以进入老年代。

    你看,如果真的是如上面所说的规则。超过一半空间,该年龄或大于该年龄的对象,都进入老年代。

    那还有年龄3的对象什么事呢?

    因为年龄3的对象,是从年龄2对象来的,而年龄2对象是从年龄1中的对象来的。

    进入老年代的应该在年龄1的对象。压根不会不发展到年龄3的对象。

    但真的是这样子吗?

    肯定不是,让超过survivor区域一般的年龄1的对象直接进入老年代。JVM的设计者疯了吗?

    还是书本的描述有错呢?

    真实情况是这样子的:

    年龄1+年龄2+年龄3+年龄N的对象加起来的空间,大于survivor区域的一半,就会让年龄N和年龄N以上的对象进入老年代。动态年龄判断应该是这样子的。说的通俗一点:就是年龄从小到大对象的占据空间的累加和,而不是某一个特定年龄对象占据的空间。

    有没有被书本骗了的感觉。。。。

    被书本骗了.png

    好嘛,如果你还不信。

    Talk is cheap,Show me the money

    image

    搞错了,重来

    Talk is cheap ,Show me the code。

    uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) {
        //survivor_capacity是survivor空间的大小
      //desired_survivor_size就是动态年龄判断是否对象进入老年代的阈值
      //TargetSurvivorRatio:默认50
      size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);
      size_t total = 0;
      uint age = 1;
      while (age < table_size) {
      //sizes数组是每个年龄段对象大小
      //total就是年龄从小到大的对象占据的空间累加和
        total += sizes[age];
      //如果累加和大于阈值,就直接跳出循环,假设磁盘的age等于3吧
        if (total > desired_survivor_size) break;
        age++;
      }
      //MaxTenuringThreshold上限是15,现在age是3,那么result就是等于3
      uint result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold;
        ...
    }
    
    

    上面这段代码,也证实了我的猜想:

    真正的动态年龄判断:是年龄从小到大的对象占据的空间,大于survivor区域的一半,然后把等于或大于该年龄的对象,放入到老年代。

    小结

    这就是书本理理论和实践的差距吧。你不真正看一下源码,可能一直都以为书本说的是真的。这也从侧面说明了:源码无秘密。

    补充知识

    • 大对象直接进入老年代。
      • 那多大的对象是大对象?大于下面参数的对象,就是大对象
      • 直接通过:-XX:PretenureSizeThreshold来配置
    • 动态年龄判断
      • 里面涉及到一个值,就是survivor区域的一半,其实也不一定是一半,你可以自定义的
      • 参数:-XX:TargetSurvivorRatio
    • 年龄大于阈值,进入老年代
      • 这个阈值:JDK8后,范围是1-15
      • 参数:XX:MaxTenuringThreshold

    好了,说完了。有收获的话,记得点赞和转发哈哈哈。不然,打哭你(霸气侧漏)

    image

    相关文章

      网友评论

          本文标题:JVM-动态年龄判断你真的理解了吗

          本文链接:https://www.haomeiwen.com/subject/rlaakltx.html