老年代垃圾回收算法

根据上一章所讲还留下了几个问题

1.万一垃圾回收过后,存活下来的对象超过了10%的内存空间,在另外一块Survivor区域中放不下咋办

2.万一我们突然分配了一个超级大的对象,大到啥程度?新生代找不到连续内存空间来存放,此时咋整?

3.到底一个存活对象要在新生代里这么来回倒腾多少次之后才会被转移都老年代去?

 

先说第3点,老年代默认进入规则

1.躲过15次GC之后进入老年代

老年代垃圾回收算法

 

 

 比如这行代码,只有kafka类一直存在,那么静态变量就一直有引用。所以垃圾回收不会做处理

没“幸存”一次就会对该对象的年龄+1岁,默认设置下,15岁进入老年代

该参数可以通过设置  “-XX:MaxTenuringThreshold”来设置

 

2.动态年龄判断

比如说,在当前存放的survivor区域中,如果一批对象的大小大于该survivor区域的50%,那么大于这批对象年龄的对象直接进入老年代

老年代垃圾回收算法

 

假设这个图里的Survivor2区有两个对象,这俩对象的年龄一样,都是2岁
然后俩对象加起来对象超过了50MB,超过了Survivor2区的100MB内存大小的一半了,这个时候,Survivor2区里的大于等于2岁的对
象,就要全部进入老年代里去。

 

  另外这里要理清楚一个概念,就是实际这个规则运行的时候是如下的逻辑:年龄1+年龄2+年龄n的多个年龄对象总和超过了Survivor区
域的50%,此时就会把年龄n以上的对象都放入老年代。

 3.大对象直接进去老年代

  参数 “ -XX:PretenureSizeThreshold”,可以把他的值设置为字节数,比如“1048576”字节,就是1MB。

  这个参数的意思是,如果要创建大于等于该值得对象,直接存入老年代,避免大对象在年轻代几块内存区中转移的系统消耗开支

 

现在说第1点

  就是如果在Minor GC之后发现剩余的存活对象太多了,没办法放入另外一块Survivor区怎么办?如下图。

 

 

老年代垃圾回收算法

 

  比如上面这个图,假设在发生GC的时候,发现Eden区里超过150MB的存活对象,此时没办法放入Survivor区中,此时该怎么办呢?
  这个时候就必须得把这些对象直接转移到老年代去,如下图所示。

 老年代垃圾回收算法

 

上面放入老年代又引起了一个新的问题,如果老年代也放不下怎么办

  首先,在执行任何一次Minor GC之前,JVM会先检查一下老年代可用的可用内存空间,是否大于新生代所有对象的总大小。

为啥检查这个呢?因为最极端的情况下,可能新生代Minor GC过后,所有对象都存活下来了,那岂不是新生代所有对象全部要进入老
年代?如下图。
老年代垃圾回收算法

  如果说发现老年代的内存大小是大于新生代所有对象的,此时就可以放心大胆的对新生代发起一次Minor GC了,因为即使Minor GC之
后所有对象都存活,Survivor区放不下了,也可以转移到老年代去。

 

  假如Minor GC之前,发现老年代的可用内存已经小于了新生代的全部对象大小了,就会看一个“-XX:-HandlePromotionFailure”的参数是否设置了

如果设置了该参数,则会判断当前老年代的内存大小是否大于之前每一次minor GC后进入老年代的对象的平均大小

 老年代垃圾回收算法

 

 

如果该评断失败,或者参数没有设置会触发一次 “”FULL GC“,对老年代进行一次垃圾回收然后再进行Minor GC将新生代对象转入

如果判断成功

可以冒险尝试一下Minor GC

此时有几种可能:

  第一种可能,Minor GC过后,剩余的存活对象的大小,是小于Survivor区的大小的,那么此时存活对象进入Survivor
区域即可。(通过)
  第二种可能,Minor GC过后,剩余的存活对象的大小,是大于 Survivor区域的大小,但是是小于老年代可用内存大小
的,此时就直接进入老年代即可。(放入老年代)
  第三种可能,很不幸,Minor GC过后,剩余的存活对象的大小,大于了Survivor区域的大小,也大于了老年代可用内
存的大小。此时老年代都放不下这些存活对象了,就会发生“Handle Promotion Failure”的情况,这个时候就会触
发一次“Full GC”。(Full GC)

Full GC就是对老年代进行垃圾回收,同时也一般会对新生代进行垃圾回收。

 

如果要是Full GC过后,老年代还是没有足够的空间存放Minor GC过后的剩余存活对象,那么此时就会导致所谓的
“OOM”内存溢出了

  

 

上一篇:【冲刺大厂P6专题】JVM内存为什么要分成新生代,老年代,持久代?新生代中为什么要分为Eden和Survivor?


下一篇:JVM内存分配策略