jvm 垃圾收集器
再忙再累,不忘垃圾分类!!!
年轻代(复制算法)
Serial 收集器
单线程收集器。单线程的意义不仅仅说明只是通过一个cpu或者或者一个线程去完成垃圾收集,更重要的是垃圾收集器在工作时,会暂停其他所有的工作线程(STW:Stop The Word)。
优点:client模式的首选,简单高效,没有线程切换的开销。
ParNew 收集器
Serial收集器的多线程版本。除了使用多线程进行垃圾收集外,其他的功能和Serial收集器基本一致,在实现上二者共用了很多代码。
优点:ParNew是很多server模式下虚拟机年轻代垃圾收集器的首选,原因是:除Serial ,只有ParNew可以与cms收集器配合。
注意:单cpu环境,ParNew的收集效率没有Serail收集器高。因为ParNew存在线程的开销。
parallel Scavenge 收集器
新生代、复制算法、多线程,看起来和ParNew没什么区别。
实际上,parallel Scavenge 收集器和其他垃圾收集器的关注点不同:① 其他收集器关注的是尽可能的缩短用户程序运行时垃圾收集造成的停顿时间;② parallel Scavenge 收集器关注的是可控的吞吐量。吞吐量=CPU运行用户代码耗时/(CPU运行用户代码耗时+垃圾收集的时间)。
垃圾收集时间造成的停顿时间越短,对用户的体验越好,越适合与用户交互的程序。而高吞吐量则可以高效的利用cpu,尽快完成cpu的运算任务,主要适合密集型的运算不需要与用户交互的任务。
此外,parallel Scavenge 收集器提供一个参数开关 XX:+AdaptiveSizePolicy,打开后就不用手工指定年轻代和年老代的比例,虚拟机会自动调节这些参数以达到最大的吞吐量。自适应调节策略也是ParNew和Parallel Scavenge的重要区别。
但是,自适应调节策略开启后,年轻代的大小可能会被调节的很小(不在按照8:1:1),大的对象可能会直接进入年老代,导致full GC 频繁(这可能是个坑)
年老代(标记整理)
serial old (PS MarkSweep)
1.serial old是serial的老年代版本,单线程,标记整理
2.存在的主要意义是给client模式的虚拟机使用
3.server模式下有两大用处:
3.1 在jdk1.5之前与Paraller Scavenge配合使用
3.2 cms的预备方案,在cms异常时使用
parallel old
parallel Scavenge的老年版本。该收集器是jdk1.6提供的,在此之前,如果年轻带选择了parallel Scavenge,老年代只能选择serial old ,老年代单线程无法充分利用cpu的处理能力,会无法发挥parallel Scavenge的高吞吐量的性能。
CMS(Concurrent Mark Sweep) 收集器
已获取最短停顿时间为目标的垃圾收集器。
如果你的服务希望系统停顿时间少,给用户带来较好的体验,cms非常符合。
cms基于标记-清除算法实现的,整个过程分为四个步骤
1 初始标记(STW): 标记下GC Roots 能直接关联到的对象,速度很快
2 并发标记:GC Roots Tracing 过程
3 重新标记(STW):修正并发标记期间因为用户程序继续运作而导致标记产生变动的那一部分,该部分停顿时间比初始标记长,但远没有并发标记长
4 并发清除
由于耗时较长的并发标记和并发清除可以与用户线程一起工作,所以,从总体上来说,cms收集器工作是和用户线程一起并发执行的。
缺点:
1 对cpu资源相当敏感:
在并发阶段虽然不会停掉用户程序,但是会因为占用一部分资源(线程或者cpu),导致用户程序变慢,总吞吐量降低。
cms默认启动回收线程数为:(cpuNum+3)/4 。很明显,当cpu个数少时,如2个,则回收线程为1,本来资源就紧张,还需要一半的资源来回收资源。
2 无法处理浮动垃圾
cms并发清理阶段用户程序还在运行着,不断的有新的垃圾产生,这部分垃圾就是浮动垃圾。本次cms收集不会清理浮动垃圾,也就是说老年代不能等到完全被填满了在进行收集,需要预留
一部分空间来支持正在进行的程序。如果预留的空间无法满足程序的需要就会出现一次 Concurrent Mode Failure,这时虚拟机就会启动预备方案(Searil old)。
因此,针对增速较慢的年老代,预留空间可以设置的小一点。
3 空间碎片
空间碎片是标记-清除算法的通病。空间碎片太多,会给大对象分配内存带来很大麻烦,虽然年老代有很大的空间,但是没有连续的空间足以分配大的对象,不得已提前
触发一次fullGc。cms收集器提供一个参数:XX:+UseCMSCompactAtFullCollection 控制是否在fullGC后进行碎片整理,该过程不是并发的,会导致停顿时间变长。
此外还提供一个参数: -XX:CMSFullGCBeforeCompaction=5 控制在执行多少次不压缩的fullGc后,执行一次碎片整理。