Young GC和Full GC分别在什么情况下会发生
Young GC的触发时机
Young GC其实一般就是在新生代的Eden区域满了之后就会触发,采用复制算法来回收新生代的垃圾
Old GC和Full GC的触发时机
下面几种情况:
(1)发生Young GC之前进行检查,如果“老年代可用的连续内存空间” < “新生代历次Young GC后升入老年代的对象总和的平均大小”,说明本次Young GC后可能升入老年代的对象大小,可能超过了老年代当前可用内存空间。
此时必须先触发一次Old GC给老年代腾出更多的空间,然后再执行Young GC。
(2)执行Young GC之后有一批对象需要放入老年代,此时老年代就是没有足够的内存空间存放这些对象了,此时必须立即触发一次Old GC
(3)老年代内存使用率超过了92%,也要直接触发Old GC,当然这个比例是可以通过参数调整的其实说白了,上述三个条件你概括成一句话,就是老年代空间也不够了,没法放入更多对象了,这个时候务必执行Old GC对老年代进行垃圾回收。
顺便说一句,大家在很多地方看到一个说法,意思是说Old GC执行的时候一般都会带上一次Young GC
可能很多人不理解,其实如果你把咱们这里的几个条件分析清楚了就知道了,一般Old GC很可能就是在Young GC之前触发或者在Young GC之后触发的,所以自然Old GC一般都会跟一次Young GC连带关联在一起了。
另外一个,在很多JVM的实现机制里,其实在上述几种条件达到的时候,他触发的实际上就是Full GC,这个Full GC会包含Young GC、Old GC和永久代的GC。
也就是说触发Full GC的时候,可能就会去回收年轻代、老年代和永久代三个区域的垃圾对象。
但是这个东西其实没办法给大家一个准确的定义,说到底触发Full GC的时候,是先执行Young GC?还是先执行Old
GC。
因为不同的Full GC触发条件其实是不一样的,而且不同的JVM版本的实现机制也不同。
所以很多时候,我们也只能给大家笼统的概括一句:上述条件满足时触发Full GC,Full GC一般会带上一次Young GC去回收新生代,同时也会有Old GC也回收老年代,还会去回收永久代。
永久代满了之后怎么办?
大家现在既然都知道了,Full GC有上述几个触发条件,同时触发Full GC的时候其实会带上针对新生代的Young GC,也会有针对老年代的Full GC,还会有针对永久代的GC。
所以假如存放类信息、常量池的永久代满了之后,就会触发一次Full GC。这样Full GC执行的时候,就会顺带把永久代中的垃圾给回收了,但是永久代中的垃圾一般是很少的,因为里面存放的都是一些类,还有常量池之类的东西,这些东西通常来说是不需要回收的。
如果永久代真的放满了,回收之后发现没腾出来更多的地方,此时只能抛出内存不够的异常了。