java垃圾收集器主要分为两种,串行和并行。
顾名思义,串行是单线程的,并行是多线程的。当垃圾收集器回收时,程序会停止运行,并行回收适合吞吐量大的系统。什么是吞吐量:吞吐量表示在单位时间内通过某个网络或接口的数据量 ,包括全部上传和下载的流量。
- Serial收集器
Serial(串行)垃圾收集器是最基本、发展历史最悠久的收集器;
JDK1.3.1前是HotSpot新生代收集的唯一选择,最稳定效率最高的收集器,但是因为是单线程的原因,可能会产生较长的停顿,由于它的高性能,适用于一些小型应用。
通过JVM参数-XX:+UseSerialGC可以使用串行垃圾回收器。 - ParNew收集器
ParNew收集器就是在Serial收集器的基础上实现的多线程版本,新生代并行,老年代串行,这么设计的原因是因为新生代中对象朝生夕死,处理的比较多,所有用就是并行,老年代因为对象存活的比较久,处理次数相对较少,所以用串行。
参数控制:-XX:+UseParNewGC ParNew收集器
-XX:ParallelGCThreads 限制线程数量 - Parallel 收集器
Parallel Scavenge收集器类似ParNew收集器,是新生代的收集器之一,Parallel收集器更关注系统的吞吐量。可以通过参数来打开自适应调节策略,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或最大的吞吐量;也可以通过参数控制GC的时间不大于多少毫秒或者比例;新生代复制算法、老年代标记-压缩,Parallel Scavenge收集器能够配合自适应调节策略,把内存管理的调优任务交给虚拟机去完成。采用多线程来通过扫描并压缩堆。
特点:停顿时间短,回收效率高,对吞吐量要求高。
适用场景:大型应用,数据量比较大的应用,运算系统。 - CMS收集器
CMS(Concurrent Mark Sweep),Mark 标记 Sweep清除,可以看出CMS收集器是基于标记清除算法的,一种以获取最短回收停顿时间为目标的收集器。CMS收集器是老年代的垃圾收集器,一般情况下会有ParNew来配合执行(默认情况下也是ParNew),ParNew也是使用并行的算法来执行年轻代的回收。
CMS收集的步骤为:
初始标记:需要停止运行程序的,初始标记仅仅只是标记一下GC Roots能关联到的对象。
并发标记:进行GC Roots Tracing 的过程,就是追踪与GC Roots关联的对象是否还在使用中。
重新标记:在上一步并发标记时,程序是在运行的,会产生新的垃圾对象,对象地址也有所变动,所以需要重新标记一下,但是这样也会导致程序暂停。
并发清除:这个阶段就是清除垃圾对象,因为是并行运行的,所以这时也会产生新的垃圾,但是这些垃圾是清理不掉的,因为没有被标记,所以只有等下次GC回收。
这种算法是有缺陷的,因为使用的是标记-清除算法,所以会产生内存碎片,无法回收并发清除阶段产生的垃圾, 对CPU资源很敏感, - G1收集器
在G1中,堆被划分成 许多个连续的区域(region)。为解决CMS算法产生空间碎片和其它一系列的问题缺陷.G1中提供了三种模式垃圾回收模式,young gc、mixed gc 和 full gc,在不同的条件下被触发。
发生在年轻代的GC算法,一般对象(除了巨型对象)都是在eden region中分配内存,当所有eden region被耗尽无法申请内存时,就会触发一次young gc.
当越来越多的对象晋升到老年代old region时,为了避免堆内存被耗尽,虚拟机会触发一个混合的垃圾收集器
如果内存中的mixed gc来不及回收,导致老年代被填满,就会触发一次full gc,G1的full gc算法就是单线程执行的serial 收集器,会导致异常长时间的暂停时间。