共计 1597 个字符,预计需要花费 4 分钟才能阅读完成。
027-Young GC和Full GC分别在什么情况下会发生
大厂面试题:Young GC和Full GC分别在什么情况下会发生?
1. 概述
统一用Young GC指代年轻代gc,用Old GC指代老年代GC,用Full GC指代年轻代、老年代、永久代共同的gc
。
2. Young GC的触发时机
Young GC其实一般就是在新生代的Eden区域满了之后就会触发,采用复制算法来回收新生代的垃圾
3. Old GC和Full GC的触发时机
其实之前的文章里也对Old 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的时候,可能就会去回收年轻代、老年代和永久代三个区域的垃圾对象。
后面会带大家用各种代码模拟出各种场景,然后观察JVM GC日志,大家会看到,其实满足上述一些条件的时候,在GC日志中看到的就是Full GC的字样,同时在Full GC中大家会看到同时对年轻代、老年代、永久代都进行了垃圾回收。
但是这个东西其实没办法给大家一个准确的定义,说到底触发Full GC的时候,是先执行Young GC?还是先执行Old GC。
因为不同的Full GC触发条件其实是不一样的,而且不同的JVM版本的实现机制也不同。
所以很多时候,我们也只能给大家笼统的概括一句:上述条件满足时触发Full GC,Full GC一般会带上一次Young GC去回收新生代,同时也会有Old GC也回收老年代,还会去回收永久代。
4. 永久代满了之后怎么办?
大家现在既然都知道了,Full GC有上述几个触发条件,同时触发Full GC的时候其实会带上针对新生代的Young GC,也会有针对老年代的Full GC,还会有针对永久代的GC。所以假如存放类信息、常量池的永久代满了之后,就会触发一次Full GC。
这样Full GC执行的时候,就会顺带把永久代中的垃圾给回收了,但是永久代中的垃圾一般是很少的,因为里面存放的都是一些类,还有常量池之类的东西,这些东西通常来说是不需要回收的。如果永久代真的放满了,回收之后发现没腾出来更多的地方,此时只能抛出内存不够的异常了。
5. 本文总结
上篇文章和这篇文章,基本上就把各种GC的概念给屡清楚了,同时结合之前学习到的知识,清楚的限定了各种GC的触发时机。其实整体知识框架跟之前基本上是匹配和吻合的,只不过在各种细化的概念上,做了很多的澄清和限定。