易错问题】Major GC和Full GC的区别是什么?触发条件呢?
相信大多数人的理解是Major GC只针对老年代,Full GC会先触发一次Minor GC,不知对否?我参考了R大的分析和介绍,总结了一下相关的说明和分析结论。
在基于HotSpotVM的基础角度
针对HotSpot VM的实现,它里面的GC其实准确分类只有两大种:
Partial GC(部分回收模式)
Partial GC代表着并不收集整个GC堆的模式
- Young Generation GC(新生代回收模式):它主要是进行回收新生代范围内的内存对象的GC回收器。
- Old/Tenured Generation GC(老年代回收模式):它主要是针对于回收老年代Old/Tenured Generation范围内的GC垃圾回收器(CMS的Concurrent Collection是这个模式)。
- Mixed Generation GC(混合代回收模式):收集整个young gen以及部分old gen的GC。只有G1有这个模式
Full GC(全体回收模式)
Full GC代表着收集整个JVM的运行时堆+方法区+直接堆外内存的总体范围内。(甚至可以理解为JVM进程范围内的绝大部分范围的数据区域)。
它会涵盖了所有的模式和区域包含:Young Gen(新生代)、Tenured Gen(老生代)、Perm/Meta Gen(元空间)(JDK8前后的版本)等全局范围的GC垃圾回收模式。
在一般情况下Major GC通常是跟Full GC是等价的,收集整个GC堆。但如果从HotSpot VM底层的细节出发,如果再有人说“Major GC”的时候一定要问清楚他想要指的是上面的Full GC还是Old/Tenured GC。
基于最简单的分代式GC策略
触发条件是:Young GC
按HotSpot VM的Serial GC的实现来看,当Young gen中的Eden区分达到阈值(属于一定的百分比进行控制)的时候触发。
注意:Young GC中有部分存活对象会晋升到Old/Tenured Gen,所以Young GC后Old Gen的占用量通常会有所升高。
触发条件是:Full GC
- 当准备要触发一次Young GC时,如果发现统计数据说之前Young Old/Tenured Gen剩余的空间大,则不会触发Young GC,而是转为触发Full GC(因为HotSpot VM的GC里,除了CMS的Concurrent collection之外,其它能收集Old/Tenured Gen的GC都会同时收集整个GC堆,包括Young gen,所以不需要事先触发一次单独的Young GC);
- 如果有Perm/Meta gen的话,要在Perm/Meta gen分配空间但已经没有足够空间时,也要触发一次full GC。
- System.gc()方法或者Heap Dump自带的GC,默认也是触发Full GC。HotSpot VM里其它非并发GC的触发条件复杂一些,不过大致的原理与上面说的其实一样。
注意:Parallel Scavenge(-XX:+UseParallelGC)框架下,默认是在要触发Full GC前先执行一次Young GC,并且两次GC之间能让应用程序稍微运行一小下,以期降低Full GC的暂停时间(因为young GC会尽量清理了Young Gen的垃圾对象,减少了Full