1.JVM垃圾收集器
JVM在历史长河里面出现了很多的垃圾收集器,咱们总结一下
新生代收集器:Serial、ParNew、Parallel Scavenge
老年代收集器:CMS、Serial Old、Parallel Old
整堆收集器: G1
在后面就是ZGC了。
Serial和Serial Old是串行的垃圾回收器,一般是在早期内存比较小的时候才会使用到的。
Parallel Scavenge、Parallel Old是并行的垃圾收集器,也就是所谓的PS+PO,目前好多公司没有优化的时候都是用的这个。
CMS是最早并发的垃圾收集器,给JVM开辟了一片新的天地,可以在运行程序的同时进行垃圾的收集,当然CMS在来及收集的时候会出现很多的问题。
G1也就是在CMS之上进行了一些优化,当然他也是并行的垃圾收集器。
ZGC也就是最近比较新的一款垃圾收集器了,他抛弃了之前的好多东西,但是他在大内存里面的垃圾收集器的效果听说还是很好的。
2.有没有问到过CMS的问题
为什么每次面试的时候都会问到CMS的垃圾收集器呢?
不仅仅是因为他是第一款并发的垃圾收集器,而且CMS里面有一些很多需要优化的地方。
首先第一点肯定就是看看CMS带给我们的问题有哪些?
第一个:因为是并发的垃圾收集器,所以肯定会带来一些浮动垃圾,也就是在进行垃圾收集的时候会产生一些垃圾,这些我们要怎么处理。
第二个:因为CMS的垃圾收集器的算法是使用的是标记清除,这就给老年代的内存里面会产生一些内存碎片化的问题,这个也是比较严重的问题。
第一个问题,其实很好解决,这次没有回收,下次回收就好了。但是第二个问题就不怎么好解决了。
既然出现了,那么肯定对这个内存碎片化的问题进行了一些优化了,那么是怎么做的呢?CMS设置了一个参数(-XX:CMSFullGCsBeforeCompaction),在进行了几次CMS垃圾收集器之后在进行一次内存碎片的整理,默认情况下是0,也就是每次进行CMS垃圾收集完了之后都要进行一次碎片的整理,而且还是使用的串行收集器来整理的,这个时间就会很慢了。
但是为什么不把这个参数值设置大一些呢?这样在几次CMS之后触发一次串行的垃圾整理也挺好的呀。但是真实情况真的就是这样的么?如果在CMS回收完了没有进行内存整理,这样在YGC之后,没有连续的区域来存放进入老年代的对象,这个时候也会触发内存的整理,一样也是串行去操作的,这样是不是更消耗时间了呢?我们曾经把这个值调过2,最后的效果还没有默认的情况好一些呢。
接下来就是在CMS在进行的同时,又产生了一批垃圾,切老年代里面也没有地方存在这批新产生的老年代对象,这个时候就会触发串行,进行碎片整理,那么这个我们有没有什么好的办法来避免他呢?CMS里面有个参数是-XX:CMSInitiatingOccupancyFraction,他是设置老年代内存使用占比到多少的时候触发CMS,默认值是92,也就是老年代的大小到了92%的时候才会触发CMS垃圾收集器,那么就很明显了,在只有8%空间的情况下,在产生新的老年代对象,就会很容易的触发串行的碎片整理了,我们只需要把这个值改小一些就好了。
当然除了上面的两个参数还有很多很多的参数都是可以调的,但是小编目前来说遇到的比较多的就是这两个参数就可以解决大部分问题了。
网上还查到一个参数-XX:CMSScavengeBeforeRemark,这参数默认情况下是不开启的,他的意思就是在每次CMS收集前,进行一次YGC,这样就可以保证不会再并发收集的同时还会产生新的老年代对象。
3.G1垃圾收集器
G1也是有分代的,但是他是逻辑分代,物理部分的。
G1里面默认情况下是分为2048个Region的,当然这个可以根据设置的Region大小来调整,一般情况下没有太大必要调整。每个Region被标记了E、S、O和H,E就是eden区,S就是survivor区,O就是old区,上面三个就是分代的里面概念了,那么H又代表什么区呢?H表示Humongous,这个Region存储的是一些大对象的区域。
G1垃圾收集器里面有三种模式的GC:young gc、mixed gc和full gc,其实young gc和full gc就好理解了,那么mixed gc又是什么呢?
当越来越多的对象晋升到老年代old region时,为了避免堆内存被耗尽,虚拟机会触发一个混合的垃圾收集器,即mixed gc,该算法并不是一个old gc,除了回收整个young region,还会回收一部分的old region,这里需要注意:是一部分老年代,而不是全部老年代,可以选择哪些old region进行收集,从而可以对垃圾回收的耗时时间进行控制。
那么mixed gc在什么时候触发的呢?G1里面有个参数-XX:InitiatingHeapOccupancyPercent,这个就是在内存占用的百分比到了多少之后在触发mixed gc,默认情况下是45%,虽然是45%,但是在极端的情况下,还是会产生full gc的,如果在G1里面还会频繁的Full gc,这样时候我们就可以调整一下这个参数,让他提早触发mixed gc就可以了
4.下期预告,CMS和G1的异同
CMS和G1都是并发收集器,他们在并发标记的时候都用到了三色标记算法。
大家可以参考一下下面的这篇文档