垃圾收集器


1. Serial 收集器

      ("Serial" is a stop-the-world, copying collector which uses a single GC thread.)

  Serial收集器是最基本,历史最悠久的收集器,使用复制算法,在jdk 1.3.1之前是 虚拟机新生代收集的唯一选择,它是单线程的收集器,它在进行垃圾收集时,必须暂停其他所有的工作线程(Sun将其称为"stop the world"),直到它收集结束。"stop the world"这项工作实际上是由虚拟机在后台自动发起和自动完成的,在用户看不见的情况下把用户的正常工作线程全部停掉,这对很多应用是难以接受的。

  但它依然是虚拟机运行在Client模式下的默认新生代收集器。其优点:简单而高效,对于限定单个CPU的环境来讲,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率。在用户的桌面应用场景中,分配给虚拟机的管理内存一般不会很大,收集几十兆至一百兆的新生代,停顿时间完全可以控制在几十毫秒最多一百多毫秒以内,只要不是频繁发生,这点停顿是可以接受的。所以Serial收集器对于运行在Client模式下的虚拟机来讲是一个很好的选择。

 

2.ParNew收集器

      "ParNew" is a stop-the-world, copying collector which uses multiple GC threads. It differs from "Parallel Scavenge" in that it has enhancements that make it usable with CMS. For example, "ParNew" does the synchronization needed so that it can run during the concurrent phases of CMS.

  ParNew收集器其实就是Serial收集器的多线程版本,使用复制算法,除了使用多线程进行垃圾收集之外,其余行为包括Serial收集器可用的所有控制参数(例如:-XX:SurivorRatio,-XX:PretenureSizeThreshod,-XX:HandlePromotionFailure等),收集算法,Stop the world,对象分配规则,回收策略等都与Serial收集器完全一样,实现上这两种收集器也公用了相当多的代码。

   ParNew是许多运行在Server模式下的虚拟机首选的新生代收集器,其中有一个与性能无关但很重要的原因是:除了Serial收集器外,目前只有它能与CMS收集器配合工作。ParNew收集器也是使用-XX:+UseConcMarkSweepGC选项后的默认新生代收集器,也可以使用-XX:+UseParNewGC选项来强制指定它。

  ParNew在CPU下不会比Serial收集器有更好的效果,其适合在多CPU中使用。它默认开启的收集线程数与CPU数量相同,在CPU非常多(比如32,现在动辄就4核加超线程,服务器超过32个逻辑CPU的情况越来越多了)的环境下,可以使用-XX:ParallelGCThreads参数来限制垃圾收集的线程数。

 

3. Parallel Scavenge收集器

    "Parallel Scavenge" is a stop-the-world, copying collector which uses multiple GC threads.

  其也是一个新生代收集器,它也是使用复制算法的收集器,又是并行的多线程收集器,看上去和ParNew类似。但Parallel Scavenge的特点是它的关注点与其他收集器不同,CMS等收集器的关注点尽可能地缩短垃圾收集时用户线程的停顿时间,而Parallel Scanvenge收集器的目标则是达到一个可控的吞吐量。所谓吞吐量就是CPU用于运行用户代码时间与CPU总消耗时间的比值,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间),如果虚拟机总共运行了100分钟,其中垃圾收集器花掉1分钟,那吞吐量就是99%。

   停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能提升用户的体验;而高吞吐量则可以高效的利用CPU时间,尽快完成程序的运行任务,主要适合在后台运算而不需要太多交互的任务。

 Parallel Scavenge 收集器提供了两个参数用于控制吞吐量,分别是控制最大垃圾收集器停顿时间的-XX:MaxGCPauseMillis参数及直接设置吞吐量大小的-XX:GCTimeRatio参数。

  MaxGGPauseMillis参数允许的值是一个大于0的毫秒数,收集器将尽力保证内存回收花费的时间不超过设定值。不过大家不要以为把这个参数设置的小点就能使系统的垃圾收集速度更快,GC停顿时间缩短是以牺牲吞吐量和新生代空间来换取的:系统把新生代调小一些,收集300M的新生代肯定比收集500M的快吧,这也直接导致垃圾收集发生的更频繁些,原来10秒收集一次,每次停顿100毫秒,现在变成5秒收集一次,每次停顿70毫秒。停顿时间缩短了,但吞吐量也下来了。

  GCTimeRatio参数的值应该是一个大于0小于100的整数,也就是垃圾收集时间占总时间的比率,相当于是吞吐量的倒数。如果把此参数设置为19,那么允许的最大GC时间就站总时间的5%(即1/(1+19)),默认值为99,就是允许最大1%(即1/(1+99))的垃圾收集时间。

  由于与吞吐量关系密切,Parallel Scavenge收集器也经常被称为“吞吐量优先”收集器。

 

4.Serial Old收集器

     "Serial Old" is a stop-the-world, mark-sweep-compact collector that uses a single GC thread

  Serial Old是Serial收集器的老年代版本,它同样是一个单线程收集器,使用“标记-整理”算法。这个收集器的主要意义也是被Client模式下的虚拟机使用。如果在Server模式下,它主要还有两大用途:一个是在JDK1.5及之前的版本中与Parallel Scavenge收集器搭配使用,另一个就是作为CMS收集器的后备预案,在并发收集器发生Concurrent Mode Failure的时候使用。

5.Parallel Old 收集器

    "Parallel Old" is a compacting collector that uses multiple GC threads.

  Parallel Old是Parallel Scavenge 收集器的老年代版本,使用多线程和“标记-整理”算法。这个收集器是在JDK1.6中才开始提供的,在此之前,新生代的Parallel Scavenge收集器一直处于比较尴尬的状态。原因是,如果新生代选择了Parallel Scavenge收集器,老年代出来Serial Old收集器别无选择(Parallel Scavenge 收集器无法与CMS收集器配合工作)。由于单线程的老年代Serial Old收集器在服务器应用性能上的拖累,即使用了Parallel Scavenge收集器也未必能在整理上获取吞吐量最大化的效果。

  知道parallel Old收集器出现后,“吞吐量优先”收集器终于有了名副其实的组合,在注重吞吐量及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge+Parallel Old收集器。

6.CMS收集器

      "CMS" is a mostly concurrent, low-pause collector.

  CMS(Concurrent Mark Sweep)收集器是一种以获得最短回收停顿时间为目标的收集器。目前很大一部分的java应用都集中在互联网或者B/S系统的服务器端,这类应用尤其重视服务的响应速度,希望系统的停顿时间最短,以给用户带来较好的体验。CMS收集器就非常符合这类应用的需求。

  从名字(包含“Mark Sweep")上就可以看出CMS是基于“标记-清理”算法实现的,它的运作过程对于前面集中收集器来说更复杂,整个过程分为4个步骤:

  初始标记(CMS initial mark)

  并发标记(CMS concurrent mark)

  重新标记(CMS remark)

  并发清除(CMS concurrent sweep)

 其中初始标记,重新标记这两个步骤仍然需要“Stop the world",初始标记只是标记一下GC Roots 能直接关联到的对象,速度很快,并发标记阶段就是进行GC Roots Tracing的过程,而重新标记阶段则是为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。

  由于整个过程中耗时最长的并发标记和并发清除过程中,收集器线程都可以与用户线程一起工作,所以总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。

7.G1收集器

  G1(Garbage First)收集器是当期收集器技术发展的最前沿成果,它与前面的CMS收集器相比有两个显著的改进:一是G1收集器是给予”标记-整理“算法实现的,也就是说它不会产生空间碎片,这对于长时间运行的应用系统来说非常重要。二是它可以非常精确地控制停顿,既能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒,这几乎已经是实时Java的垃圾收集器的特征。

  G1收集器可以实现在基本不牺牲吞吐量的前提下完成低停顿的内存回收,这是由于它能够极力地避免完全区域的垃圾收集,之前的收集器进行收集的范围都是整个新生代或者老年代,而G1将整个Java堆(包括新生代,老年代)划分为多个大小固定的独立区域,并且跟踪这些区域里面的垃圾堆积程度,在后台维护一个优先列表,每次根据允许的收集时间,优先回收垃圾最多的区域(这就Garbage First名字的由来)。区域划分及有优先级的区域回收,保证了G1收集器在有限的时间内可以获得最高的收集效率。

 

8.回收器使用参数:

  • Using the -XX flags for our collectors for jdk6,

     

  • UseSerialGC is "Serial" + "Serial Old" (使用方法  -XX:+UseSerialGC )
  • UseParNewGC is "ParNew" + "Serial Old"
  • UseConcMarkSweepGC is "ParNew" + "CMS" + "Serial Old". "CMS" is used most of the time to collect the tenured generation. "Serial Old" is used when a concurrent mode failure occurs.
  • UseParallelGC is "Parallel Scavenge" + "Serial Old"
  • UseParallelOldGC is "Parallel Scavenge" + "Parallel Old"

  

 

   

 

 

猜你喜欢

转载自dbp5588.iteye.com/blog/2366611
今日推荐