JVM(五):Major、MinorGC简述&&减少FullGC频率

Java堆可以细分为:新生代和老年代;新生代又可细分为 Eden空间、From Survivor空间、To Survivor空间等

(Tenured space是老年代)

 

Minor GC:从年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC。

Major GC 是清理老年代。

Full GC 是清理整个堆空间—包括年轻代和老年代。

 

对象优先在Eden区分配:

    HotSpot JVM把年轻代分为了三部分:1个Eden区和2个Survivor区(分别叫from和to)。默认比例为8:1。大多数情况下,对象优先在Eden区中分配。当Eden区中没有足够空间进行分配时,将会触发一次Minor GC。

大对象直接进入老年代:
    所谓的大对象是指,需要大量连续内存空间的Java对象。例如:很长的字符串或者数组。虚拟机提供了一个-XX:PretenureSizeThreshold参数。令大于这个-XX:PretenureSizeThreshold设置值的对象,直接在老年代分配。

长期存活的对象将进入老年代:
    虚拟机为了分代收集,对每一个对象定义了一个对象年龄计数器(Age)。如果对象在Eden出生,并且经过一次Minor GC后,仍然存活并且能被Survivor区中每熬过一次Minor GC,,年龄就会增加1岁。当年龄增加到默认的15岁时,就会晋升到老年代。

    晋升为老年代的阙值通过参数-XX:MaxTenuringThreshold设置。

许多 Major GC 是由 Minor GC 触发的,所以很多情况下将这两种 GC 分离是不太可能的。

这使得我们不用去关心到底是叫 Major GC 还是 Full GC,大家应该关注当前的 GC 是否停止了所有应用程序的线程,还是能够并发的处理而不用停掉应用程序的线程

 

Full GC触发条件:

(1)调用System.gc时,系统建议执行Full GC,但是不必然执行

(2)老年代空间不足——————比如连续大对象直接进入老年代

(3)方法区空间不足

(4)在执行minor gc的时候进行的一系列检查

执行Minor GC的时候,JVM会检查老年代中最大连续可用空间是否大于了当前新生代所有对象的总大小。
如果大于,则直接执行Minor GC(这个时候执行是没有风险的)。
如果小于了,JVM会检查是否开启了空间分配担保机制,如果没有开启则直接改为执行Full GC。
如果开启了,则JVM会检查老年代中最大连续可用空间是否大于了历次晋升到老年代中的平均大小,如果小于则执行改为执行Full GC。--------
如果大于则会执行Minor GC,如果Minor GC执行失败则会执行Full GC

 

简而言之,

新生代所有对象总大小 〉 老年代可用空间  且没有开启空间分配担保

历次晋升到老年代 〉老年代可用

 

啥是空间分配担保:

在发生Minor GC之前,虚拟机先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果条件成立的话,那么Minor GC确认是安全的;

如果不成立的话虚拟机就会检查HandlePromotionFailure设置值是否允许担保失败,如果允许就会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试进行着一次Minor GC,尽管这次Minor GC是有风险的,可能触发Full GC

如果小于或者HandlePromotionFailure设置不允许冒险,这时改为进行一次Full GC

 

posted on 2018-11-07 10:25  samuel1  阅读(2455)  评论(0编辑  收藏  举报

导航