如果收集算法时内存回收的方法,那么垃圾收集器就是具体的实现.Java虚拟机规范中对垃圾收集器如何实现没有规定,所以不同厂商所提供的垃圾收集器都会有很大差别,今天具体介绍一些主流的来收集器有哪些?
-
Serial收集器
这是最基本,发展历史最久的收集器。从JDK1.3到现在都是默认新生代收集器,它的原理是它会使用一个CPU或者一条线程去完成垃圾收集工作,与此同时,项目内所有的线程必须暂停其他所有的工作线程,直到它垃圾收集任务完成。缺点是:垃圾收集会暂停其他所有线程工作,优点是:因为没有其他线程的交互,可以专心做垃圾收集,可以获取到最高的单线程频率。针对用户桌面应用场景中,分配给虚拟机管理的内存一般来说不会很大,停顿时间不会太长,控制在几十毫秒最多一百多毫秒以内,只要不是频繁发生,还是可以接受的。总结,Serial收集器对于运行在client模式下的虚拟机是一个不错的选择。 -
ParNew收集器
ParNew收集器就是Serial收集器的多线程版本,唯一区别就是使用多线程进行垃圾收集,与Serial收集器一样。在效率方面:ParNew收集器在单CPU环境中绝对不会有比serial收集器更好的效果。但是多个CPU肯定会超越serial收集器,可以使用-XX:ParallelGCThreads参数来限制垃圾收集的线程数,可以使用-XX:UseParNewGC来强制指定它 -
Parallel Scavenge收集器
它是一个新生代收集器,它既实现了复制算法,又是并行的多线程收集器。那么并行:多条垃圾收集线程并行工作,用户线程处于等待状态。那么并发:用户线程和垃圾收集线程同时执行(如果多核CPU有可能并行,但是线程过多会交替执行。如果单核CPU线程基本都会替执行),它的目标是达到一个可控制的吞吐量。 吞吐量就是用户代码执行时间与CPU总消耗时间的比值。例如虚拟机总共运行了100分钟,其中垃圾收集花掉一分钟,那么吞吐量是百分之99。它提供了两个参数用于精确控制吞吐量,控制最大垃圾收集停顿时间:-XX:MaxGCPauseMillis,设置吞吐量大小:-XX:GCTimeRatio,
MaxGCPauseMillis不能设置太小,如果太小的话吞吐量就降下来,MaxGCPauseMillis就是垃圾收集时间占总时间的比率。例如设置参数为19,就是1/(1+19) = 5% -
Serial Old收集器
Serial收集器的老年代版本,是一个单线程收集器,使用的是标记-整理算法,主要是给Client模式下的虚拟机使用,如果在server模式下,一是在JDK1.5以及之前的版本与Parallel Scavenge收集器搭配使用二是作为GMS收集器的备用方案,在并发收集发生Concurrent Mode Failure时使用。 -
Parallel Old收集器
Parallel Scavenge收集器老年代版本,是一个多线程,使用的是标记-整理算法,如果比较注重吞吐量和CPU资源敏感的场景推荐使用 -
CMS收集器
它是一种以获取最短回收停顿时间为目标的收集器,现在web项目都比较注重服务的相应速度,希望系统停顿时间较短,那么这个收集器很符合你的需求,它是基于标记-清除算法,又是一个多线程收集器可以并行清除。他的运行步骤:1.初始标记2.并发标记3.重新标记4.并发清除
初始标记标记一下GC Roots能直接关联的对象,速度快。并发标记是进行GC RootsTracing的过程,重新标记是为了修正并发标记期间对象发生变化的标记 记录。并发清除是把标记对象并发清理。优点:并发收集,低停顿。缺点:因为CMS收集器是并发处理的,对用户线程运行时间有影响,总吞吐量降低。CMS收集器无法处理浮动垃圾,可能出现Concurrent Mode Failure失败而导致另一次Full GC的产生。浮动垃圾:CMS收集器并发清理阶段用户线程在运行着,伴随程序运行自然就还会有新的垃圾不断产生,这一部分垃圾出现在标记过程后,CMS无法在当前收集中处理掉它们,只好留着下一次清理。CMS收集器是基于“标记-清除”算法实现的收集器,收集结束后会有大量空间碎片产生。空间碎片过多时,将给大对象分配带来麻烦。 -
G1收集器
G1收集器是面向服务端应用的垃圾收集器。特点:
并行与并发是G1可以充分利用多CPU,多核环境下的硬件优势,使用多个CPU缩短GC执行时间。G1收集器可以通过并发的方式让Java程序继续执行。
分代收集是G1可以独立管理整个GC堆,采用不同的方式去处理新创建的或者已经存活了一段时间的对象。
空间整合是基于“标记 整理”算法实现的收集器,在局部上是基于“复制”算法实现的。通过这两种方式在运行时间不会产生内存空间碎片,收集后能提供规整的可用内存。
可预测的停顿是可以让使用者明确一个长度为多少毫秒的时间片段,消耗在垃圾收集的时间不能超过规定时间