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

看文章前,咱们先温习一下。

什么对象能力间接进入老年代?

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

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

好了嘛,应该没了吧。

这次,咱们把眼光聚焦到:动静年龄判断。

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

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

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

简略点说:在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以上的对象进入老年代。动静年龄判断应该是这样子的。说的艰深一点:就是年龄从小到大对象的占据空间的累加和,而不是某一个特定年龄对象占据的空间。

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

好嘛,如果你还不信。

Talk is cheap,Show me the money

搞错了,重来

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

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