`
m635674608
  • 浏览: 5027370 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

垃圾收集器Serial 、Parallel、CMS、G1

 
阅读更多

 这里介绍4个垃圾收集器,如果进行了错误的选择将会大大的影响程序的性能。

    时至今日,仍然有两个事情困扰着开发人员:垃圾收集(GC)和了解异性(程序猿的悲鸣),后者我确实不太了解,因为我被前者搞的无暇顾及怎么了解异性,特别是当知道在JAVA8中对这一区域有了很大的改进和提升还有移除了PermGen和以一些新的令人兴奋的调优。

    当我们谈到垃圾回收时,我们绝大多数都知道利用它的概念在我们日常的编程中。但是,当问题出现时,会发现很多是我们不知道的。JVM 最大误区之一就是它只有一个垃圾回收器,实际上是它提供了四个不同的收集器,每个都有其自身独特的优势和劣势。垃圾收集器不是自动选择的,这取决个人以及吞吐量和应用程序的差异。

这些垃圾收集的普遍存在的共同点是他们都把堆分隔成不同的片段来管理,比如在age-old区中的大多数对象应该被快速的回收。这些都是老生常谈的事,我们直接进入主题来看一下各个收集器的不同以及他们的优缺点。

1. Serial收集器

    Serial收集器是JAVA虚拟机中最基本、历史最悠久的收集器,在JDK 1.3.1之前是JAVA虚拟机新生代收集的唯一选择。Serial收集器是一个单线程的收集器,但它的“单线程”的意义并不仅仅是说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是在它进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束。

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

 

PS:开启Serial收集器的方式 -XX:+UseSerialGC

如:Xms30m -Xmx30m -Xmn10m -XX:+UseSerialGC -XX:+PrintGCDetails

-XX:+UseSerialGC的是Serial收集器,Xms30m -Xmx30m 指定了JAVA虚拟机的固定大小为30M,-Xmn10m 指JAVA新生代的空间为10M。

2. Parallel(并行)收集器

    这是 JVM 的缺省收集器。就像它的名字,其最大的优点是使用多个线程来通过扫描并压缩堆。串行收集器在GC时会停止其他所有工作线程(stop-the-world),CPU利用率是最高的,所以适用于要求高吞吐量(throughput)的应用,但停顿时间(pause time)会比较长,所以对web应用来说就不适合,因为这意味着用户等待时间会加长。而并行收集器可以理解是多线程串行收集,在串行收集基础上采用多线程方式进行GC,很好的弥补了串行收集的不足,可以大幅缩短停顿时间(如下图表示的停顿时长高度,并发比并行要短),因此对于空间不大的区域(如young generation),采用并行收集器停顿时间很短,回收效率高,适合高频率执行。

2.png

图1.Serial收集器与Parallel/ Throughput(并行)收集器的比较

3.CMS收集器

    CMS(Concurrent Mark Sweep)收集器是基于“标记-清除”算法实现的,它使用多线程的算法去扫描堆(标记)并对发现的未使用的对象进行回收(清除)。整个过程分为6个步骤,包括:

初始标记(CMS initial mark)

并发标记(CMS concurrent mark)

并发预清理(CMS-concurrent-preclean)

重新标记(CMS remark)

并发清除(CMS concurrent sweep)

并发重置(CMS-concurrent-reset)

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

    需要注意的是,CMS收集器无法处理浮动垃圾(Floating Garbage),可能出现“Concurrent Mode Failure”失败而导致另一次Full GC的产生。由于CMS并发清理阶段用户线程还在运行着,伴随程序的运行自然还会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在本次收集中处理掉它们,只好留待下一次GC时再将其清理掉。这一部分垃圾就称为“浮动垃圾”。也是由于在垃圾收集阶段用户线程还需要运行,即还需要预留足够的内存空间给用户线程使用,因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,需要预留一部分空间提供并发收集时的程序运作使用。在默认设置下,CMS收集器在老年代使用了68%的空间后就会被激活,这是一个偏保守的设置,如果在应用中老年代增长不是太快,可以适当调高参数-XX:CMSInitiatingOccupancyFraction的值来提高触发百分比,以便降低内存回收次数以获取更好的性能。要是CMS运行期间预留的内存无法满足程序需要,就会出现一次“Concurrent Mode Failure”失败,这时候虚拟机将启动后备预案:临时启用Serial Old收集器来重新进行老年代的垃圾收集,这样停顿时间就很长了。所以说参数-XX:CMSInitiatingOccupancyFraction设置得太高将会很容易导致大量“Concurrent Mode Failure”失败,性能反而降低。

 

    还有一个缺点,CMS是一款基于“标记-清除”算法实现的收集器,这意味着收集结束时会产生大量空间碎片。空间碎片过多时,将会给大对象分配带来很大的麻烦,往往会出现老年代还有很大的空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前触发一次Full GC。为了解决这个问题,CMS收集器提供了一个-XX:+UseCMSCompactAtFullCollection开关参数,用于在“享受”完Full GC服务之后额外免费附送一个碎片整理过程,内存整理的过程是无法并发的。空间碎片问题没有了,但停顿时间不得不变长了。虚拟机设计者们还提供了另外一个参数-XX: CMSFullGCsBeforeCompaction,这个参数用于设置在执行多少次不压缩的Full GC后,跟着来一次带压缩的。

 

    该算法与并行收集器的另一个缺点是吞吐量的它使用更多的 CPU,为了使应用程序提供更好的体验,通过使用多个线程来执行扫描和收集。这种情况长时间的运行会使应用程序停顿下来,可以使用提高空间来换取高效的运行。但是,这种算法的使用不是默认的。您必须指定 XX: + USeParNewGC来使用它。如果你可以提供更多的CPU资源的话以避免应用程序暂停,那么你可以使用CMS收集器。假设你的堆的大小小于 4 Gb你必须分配大于 4 GB的资源。

4.G1收集器

    G1垃圾收集器在JDK7 update 4之后对大于4G的堆有了更好的支持,G1是一个针对多处理器大容量内存的服务器端的垃圾收集器,其目标是在实现高吞吐量的同时,尽可能的满足垃圾收集暂停时间的要求。G1在执行一些Java堆空间中的全区域操作(如:全局标记)时是和应用程序线程并发进行的,因此减少了Java堆空间的中断比例。(译者注:可简单理解为减少了Stop-the-World的时间比例)。

 

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

 

首先将Java堆空间划分为一些大小相等的区域(region),每个区域都是虚拟机中的一段连续内存空间。G1通过执行并发的全局标记来确定整个Java堆空间中存活的对象。标记阶段完成后,G1就知道哪些区域基本上是空闲的。在回收内存时优先回收这些区域,这样通常都会回收相当数量的内存。这就是为什么它叫做Garbage-First的原因。顾名思义G1关注某些区域的回收和整理,这些区域中的对象很有可能被完全回收。而且G1使用了一个暂停时间预测模型使得暂停时间控制在用户指定的暂停时间内,并根据用户指定的暂停时间来选择合适的区域回收内存。

 

 

    G1确定了可回收的区域后就是筛选回收(evacuation)阶段了。在此阶段将对象从一个或多个区域复制到单一区域,同时整理和释放内存。该阶段是在多个处理器上多个线程并行进行的,因此减少了暂停时间并提高了吞吐量。G1在每一次的垃圾收集过程中都不断地减少碎片,并能够将暂停时间控制在一定范围内。这些已经是以前的垃圾收集器无法完成的了。比如:CMS收集器并不做内存整理。ParallelOld收集器只是对整个Java堆空间做整理,这样导致相当长的暂停时间。

 

Java8G1收集器的优化

    在java8 udpate 20中对G1收集器采用了字符串重复消除技术(String deduplication),之前字符串以及内部的char[]数组大量消耗了内存空间,在新的G1垃圾收集器中,将会对内存中重复的字符串进行优化,使他们指向同一个字符数组,以避免相同的字符串出现而使堆处理效率低下,你可以使用 -XX:+UseStringDeduplicationJVM参数来开启。

 

Java8PermGen

    在 Java 8 最大的变化之一删除了在堆中为类的元数据、内部字符串和静态变量分配 permgen空间的部分。过去如果加载大量的类到内存中经常会出现内存溢出异常,并且开发人员需要在这个方面做大量的工作,所以如果这段通过JVM来管理了将是一个不错误的优化。

 

 

    每个垃圾收集器都有不同的配置参数,可以通过不同的参数来提升性能和降低吞吐量。这些都取决于你的应用需求,不同的对收集方式、可忍受的停顿时间、内存的大小都不一样,所以要根据自身的需求来定制不同的配置参数。

 

http://www.zicheng.net/article/55.htm

 

http://blog.csdn.net/xrt95050/article/details/7326179

分享到:
评论

相关推荐

    7种JVM垃圾收集器特点-优劣势-及使用场景.pdf

    G1垃圾收集器是Java 7中引入的一种低停顿时间垃圾收集器,适用于具有大内存和高性能要求的应用程序。G1垃圾收集器使用多个线程来进行垃圾收集工作,并具有较高的垃圾收集性能和较低的停顿时间。 选择合适的垃圾收集...

    GCViewer,Tagtraum Industries的GCviewer之叉。tagtraum在2008年停止了开发,我的目标是改进对sun/oracle的java 1.6+垃圾收集器日志(包括g1收集器)的支持。.zip

    3. **兼容性**:支持多种Java垃圾收集器的日志格式,如Serial、Parallel、Concurrent Mark Sweep (CMS) 和G1等。 4. **自定义配置**:用户可以根据需要配置不同的视图和参数,定制化分析体验。 5. **源代码开放**:...

    JVM入门实战/arthas实战/垃圾回收算法/垃圾回收器/jvm内存模型分析

    1.1Serial/Serial Old收集器 1.2 ParNew收集器 1.3Parallel Scavenge收集器 1.4Parallel Old收集器 1.5CMS(Current Mark Sweep)收集器 1.6G1收集器 第六节:JVM参数调优 1.1 JVM重要参数介绍 1.2JVM参数调优 1.3...

    JVM垃圾收集器全面详解

    ParNew是Serial GC的多线程版本,主要在新生代进行工作,与CMS(Concurrent Mark Sweep)垃圾收集器配合使用,适合多CPU环境。它可以减少暂停时间,但可能会增加CPU使用率。 3. **Parallel GC** Parallel GC也...

    JVM初探- 内存分配、GC原理与垃圾收集器

    最后,JVM中提供了多种垃圾收集器,如Serial、Parallel、CMS、G1等,每种收集器都有其适用的场景和特点。例如,Serial收集器是单线程的,适用于小内存环境;而CMS(Concurrent Mark Sweep)收集器是追求低停顿时间的...

    Java垃圾收集器知识.pdf

    - 包括Serial、ParNew、Parallel Scavenge、CMS(Concurrent Mark Sweep)、G1(Garbage-First)等,每种收集器都有其特定的优化目标和使用场景。 10. **性能优化**: - 选择合适的垃圾收集器组合,调整JVM参数,...

    一文了解JVM全部垃圾回收器,从Serial到ZGC

    常用的7种收集器,其适用的范围如图所示Serial、ParNew、ParallelScavenge用于新生代;CMS、SerialOld、ParalledOld用于老年代。并且他们相互之间以相对固定的组合使用(具体组合关系如上图)。G1是一个独立的收集器...

    JDK19-hotspot-virtual-machine-garbage-collection-tuning-guide

    2. 对于大型应用程序,使用CMS垃圾收集器或G1垃圾收集器。 3. 对于需要低延迟的应用程序,使用Z垃圾收集器。 4. 使用 `-Xmx`和 `-Xms`选项来调整Java堆的大小。 5. 使用 `-XX:NewSize`和 `-XX:MaxNewSize`选项来调整...

    垃圾回收器(csdn)————程序.pdf

    并行收集器如ParNew和Parallel Scavenge利用多核优势提高吞吐量,而并发收集器如CMS和G1则在垃圾收集时允许应用程序继续运行,减少了STW的影响。G1是一款整堆收集器,能够跨新生代和老年代进行垃圾回收,旨在平衡...

    面试官:怎么做JDK8的垃圾收集器的调优(面试常问)

    JDK8中有多种垃圾收集器,包括Serial收集器、Parallel收集器、CMS收集器、G1收集器等,每种垃圾收集器都有其特点和适用场景。选择合适的垃圾收集器对系统的性能和稳定性具有重要影响。 Serial收集器是使用单线程...

    Java的垃圾收集器(GC)整理.pdf

    - **并行GC(Parallel GC)**:多线程的垃圾收集器,提高垃圾收集速度,但可能导致较长的暂停时间。 - **并发GC(Concurrent Mark Sweep GC, CMS)**:主要关注缩短垃圾收集时的应用暂停时间,适合响应时间敏感的...

    JDK11-hotspot-virtual-machine-garbage-collection-tuning-guide

    * Concurrent Mark-and-Sweep (CMS) 垃圾收集器:使用多线程进行垃圾收集,适合需要低 pause 时间的应用程序。 * G1 垃圾收集器:使用Region-based垃圾收集,适合需要高吞吐量和低 pause 时间的应用程序。 垃圾收集...

    JAVA 垃圾收集器与内存分配策略.rar

    - Serial GC:单线程的垃圾收集器,适用于轻量级或客户端应用。 - Parallel GC:多线程的垃圾收集器,提升回收效率,适用于服务器端应用。 - CMS(Concurrent Mark Sweep):并发标记清除,尽可能减少停顿时间,...

    JVM垃圾回收,参数,强软弱虚,常见错误OOM,与微服务结合.docx

    垃圾收集器是垃圾回收算法的落地实现,包括 Serial 串行垃圾收集器、Parallel 并行垃圾收集器、CMS 并发垃圾收集器、G1 垃圾收集器等。不同的垃圾收集器适用于不同的应用场景。 在 Java 中,可以通过命令行参数来...

    02垃圾回收器1

    本文将深入探讨几个常见的垃圾回收器,包括Serial、Serial Old、ParNew、Parallel Scavenge、CMS以及相对较新的G1收集器。 首先,Serial GC是Java虚拟机(JVM)提供的一个基础单线程收集器,主要设计用于轻量级的...

    cms-java-源码

    1. **垃圾收集算法的理解**:CMS是如何实现并发标记和清除的,以及其与其他垃圾收集器(如Serial、Parallel、G1等)的区别。 2. **JVM内存模型**:了解Java内存分配和回收的过程,以及老年代在整个内存管理中的角色...

    JVM初探内存分配GC原理与垃圾收集器共16页.pdf.z

    4. **G1 Garbage Collector**:新一代的垃圾收集器,目标是实现可预测的暂停时间模型,适合大型服务应用。 GC的调优涉及多个方面,包括设置合适的堆大小、选择合适的收集器、调整新生代与老年代的比例、优化并发比...

    理解JAVA虚拟机-内存管理、垃圾收集器.pptx

    2. **ParNew收集器**:Serial的多线程版本,常与CMS收集器配合使用。 3. **Parallel Scavenge**:关注系统吞吐量,适合CPU资源丰富的环境。 4. **Serial Old和Parallel Old**:分别对应Serial和Parallel Scavenge...

Global site tag (gtag.js) - Google Analytics