JVM各垃圾回收器优缺点及应用场景

目录

为什么需要使用垃圾收集器?

JVM各垃圾收集器特点

1、Serial收集器

2、ParNew收集器

3、Parallel Scavenge收集器

4、Serial Old收集器

5、Parallel Old收集器

6、Serial / Serial Old 收集器

7、ParNew / Serial Old收集器

8、Parallel Scavenge / Parallel Old收集器

9、CMS收集器(全名:Concurrent Mark Sweep)

10、G1收集器(全名:Garbage-First)

11、ZGC收集器(全名:Z Garbage Collector)

总结


为什么需要使用垃圾收集器?

        JVM(Java虚拟机)需要垃圾收集器是为了自动管理和回收程序运行时产生的内存中的垃圾对象,以提高内存的利用率和程序的性能。以下是几个原因:

  1. 动态分配内存:Java程序在运行时使用动态分配的内存。程序员无需显式地分配和释放内存,而是依赖于垃圾收集器来自动管理内存。这减轻了程序员的负担,并减少了内存泄漏和悬挂指针等常见的低级错误。

  2. 自动回收垃圾对象:Java程序创建的对象可能会在程序的执行过程中变得不再可访问或不再需要。如果没有垃圾收集器,这些废弃的对象将继续占用内存空间,导致内存泄漏和内存耗尽。垃圾收集器会自动识别和回收这些垃圾对象,释放内存供其他对象使用。

  3. 解决内存碎片问题:在程序执行过程中,对象的创建和销毁是动态的,可能导致内存中出现不连续的空闲内存碎片。这使得分配大对象或连续内存块变得困难。垃圾收集器通过执行内存整理操作,将存活对象移动到一起,从而减少了内存碎片,使得内存分配更加高效。

  4. 提高性能:垃圾收集器可以根据应用程序的行为和工作负载动态地调整内存回收的策略。通过优化垃圾收集的算法和策略,可以最大限度地减少垃圾收集的停顿时间,提高应用程序的响应性能和吞吐量。

        JVM需要垃圾收集器是为了自动管理内存并回收废弃对象,避免内存泄漏和内存耗尽问题,同时提高内存的利用率和程序的性能。垃圾收集器通过自动化内存管理,简化了程序员的工作,使得开发更加高效和安全。

JVM各垃圾收集器特点

垃圾收集器收集类型收集算法多线程支持目标
Serial年轻代标记-复制小型应用,停顿时间较长
ParNew年轻代标记-复制与CMS收集器搭配使用,减少停顿时间
Parallel Scavenge年轻代标记-复制高吞吐量应用,减少停顿时间
Serial Old老年代标记-整理Serial收集器无法满足的需求
Parallel Old老年代标记-整理高吞吐量应用的老年代收集
CMS年轻代和老年代标记-清除对停顿时间敏感的应用
G1年轻代和老年代分代收集大堆、低延迟的应用
ZGCRegion内存布局标记-整理大堆、极低延迟的应用

        因为部分垃圾收集器是只针对新生代或者只针对老年代的垃圾收集,所以下面开始介绍不同垃圾收集器的特点。

1、Serial收集器

Serial垃圾收集器是Java虚拟机中的一种垃圾收集器,具有以下特点:

  1. 单线程:Serial收集器是单线程收集器,即在进行垃圾收集时只使用一个线程。这意味着它只能利用单个CPU核心来执行垃圾收集操作。

  2. 标记-复制算法:Serial收集器使用"标记-复制"算法来进行垃圾收集。首先,它会标记所有活动对象,然后将存活对象复制到一个新的区域,同时清除非存活对象。这样可以保证新生代的内存空间始终是连续的。

  3. 针对新生代:Serial收集器主要用于收集新生代,即年轻代中的Eden区和Survivor区。它通过使用复制算法来实现高效的垃圾回收。

  4. 暂停应用线程:在进行垃圾收集期间,Serial收集器会暂停所有的应用线程。这意味着在垃圾收集期间,应用程序的执行将会停顿。

2、ParNew收集器

        ParNew(并行新生代)垃圾回收器是一种多线程的垃圾回收器,主要用于新生代(Young Generation)的垃圾回收。下面是ParNew垃圾回收器的特点介绍:

  1. 多线程收集器:ParNew垃圾回收器使用多线程进行垃圾回收操作,利用多核处理器的优势,可以并行地进行垃圾收集。多线程的并行性可以加快垃圾回收的速度。
  2. 标记-复制算法:ParNew垃圾回收器使用标记-复制(Mark-Copy)算法进行垃圾回收。它将新生代分为一个或多个存活区和一个空闲区,在垃圾回收过程中,将存活的对象复制到空闲区,然后清理存活区中的垃圾对象。
  3. 可与CMS收集器配合使用:ParNew垃圾回收器可以与CMS(Concurrent Mark-Sweep)收集器配合使用,在新生代进行并行的垃圾回收,而CMS收集器负责老年代的并发垃圾回收。

        需要注意的是,ParNew垃圾回收器主要关注吞吐量(吞吐量=运行用户代码的时间 / (运行用户代码的时间 + 垃圾收集时间)),而不是追求最低的停顿时间。如果应用程序对停顿时间要求非常严格,可以考虑其他的垃圾回收器,如G1或ZGC。

3、Parallel Scavenge收集器

        Parallel Scavenge(并行Scavenge)垃圾回收器是一种多线程的垃圾回收器,主要用于新生代(Young Generation)的垃圾回收。

  1. 多线程收集器:Parallel Scavenge垃圾回收器使用多线程进行垃圾回收操作,利用多核处理器的优势,可以并行地进行垃圾收集。多线程的并行性可以加快垃圾回收的速度。
  2. 高吞吐量:Parallel Scavenge垃圾回收器主要关注应用程序的吞吐量,即在给定时间内完成尽可能多的工作量。它通过并行执行垃圾回收操作来实现高吞吐量,适用于那些对吞吐量要求较高的应用场景。
  3. 标记-复制算法:Parallel Scavenge垃圾回收器使用标记-复制(Mark-Copy)算法进行垃圾回收。它将新生代分为一个或多个存活区和一个空闲区,在垃圾回收过程中,将存活的对象复制到空闲区,然后清理存活区中的垃圾对象。

        Parallel Scavenge垃圾回收器注重的是整体吞吐量,而不是追求最低的停顿时间。如果应用程序对停顿时间要求非常严格,可以考虑其他的垃圾回收器,如G1或ZGC。

4、Serial Old收集器

Serial Old收集器是Java虚拟机中的一种垃圾收集器,用于管理老年代(Old Generation)的垃圾回收。下面是Serial Old收集器的主要特点:

  1. 单线程:Serial Old是一种单线程收集器,它只使用一个线程进行垃圾回收操作。这意味着它不能充分利用多核处理器的优势,因此在并行处理能力上相对较弱。

  2. 标记-整理算法:Serial Old收集器使用标记-整理(Mark-Compact)算法进行垃圾回收。首先,它会对堆中的存活对象进行标记,然后将存活对象向堆的一端移动,最终清理掉堆的另一端上的无效对象。这样可以使得堆中的对象紧凑排列,减少了碎片化。

  3. 暂停应用线程:由于Serial Old收集器是单线程的,它在执行垃圾回收时需要暂停应用程序的执行。这就意味着在进行垃圾回收期间,应用程序的运行会发生停顿,停顿时间相对较长。对于大型的内存堆或具有复杂对象图的应用程序,停顿时间可能会更长。

  4. 与Serial收集器配合使用:Serial Old收集器通常与Serial收集器(用于年轻代)搭配使用。这种组合被称为"Serial/Serial Old"收集器组合。在这种组合中,Serial收集器负责年轻代的垃圾回收,而Serial Old收集器负责老年代的垃圾回收。

        Serial收集器适用于小型应用程序和单核处理器环境,它通过单线程和标记-复制算法来实现简单而高效的垃圾收集。然而,由于其暂停应用程序执行的特性,不适合对停顿时间要求较高的应用程序。

        随着Java虚拟机的发展,更先进的并行收集器和并发收集器被引入,它们在处理垃圾回收时提供了更好的吞吐量和较短的停顿时间。因此,在现代的Java应用程序中,Serial Old收集器的使用场景相对较少,更多地采用并行收集器(如Parallel Old)或者并发收集器(如G1、CMS、ZGC)来满足不同的需求。

5、Parallel Old收集器

        Parallel Old(并行老年代)收集器是一种多线程的垃圾回收器,专门用于老年代(Tenured Generation)的垃圾回收。

  1. 多线程收集器:Parallel Old收集器使用多线程进行垃圾回收操作,利用多核处理器的优势,可以并行地进行老年代的垃圾回收。多线程的并行性可以加快垃圾回收的速度。
  2. 高吞吐量:Parallel Old收集器注重整体吞吐量,即在给定时间内完成尽可能多的工作量。它通过并行执行垃圾回收操作来实现高吞吐量,适用于那些对吞吐量要求较高的应用场景。
  3. 标记-整理算法:Parallel Old收集器使用标记-整理(Mark-Compact)算法进行垃圾回收。在标记阶段,它会标记所有的存活对象;在整理阶段,它会将存活对象紧凑排列,释放未被引用的内存空间。

适用场景:

  1. 高吞吐量应用:Parallel Old收集器适用于对吞吐量要求较高的应用场景,例如后台任务、数据处理等。它的多线程并行能力可以加快垃圾回收速度,提高应用程序的整体吞吐量。
  2. 多核处理器:Parallel Old收集器在多核处理器上表现出色,它能够充分利用多线程并行执行垃圾回收,发挥多核处理器的优势。
  3. 长时间运行的任务:由于Parallel Old收集器的设计目标是实现高吞吐量,它适合用于长时间运行的任务,而不是对停顿时间要求非常严格的实时应用。

6、Serial / Serial Old 收集器

优点:

  1. 单线程执行:Serial收集器使用单线程进行垃圾回收操作,只有一个垃圾回收线程在工作。这简化了垃圾回收的实现,减少了线程切换和同步的开销。
  2. 简单而高效:由于Serial收集器是单线程的,因此没有多线程同步的开销,执行垃圾回收的过程相对简单且高效。
  3. 低延迟:由于只有一个垃圾回收线程在工作,因此Serial收集器的停顿时间相对较短,适合对停顿时间要求不高的应用场景。

缺点:

  1. 性能限制:由于Serial收集器只使用单个线程进行垃圾回收,无法充分利用多核处理器的优势,对于大规模数据的应用,性能可能不够理想。
  2. 高停顿时间:由于Serial收集器是单线程的,垃圾回收期间需要暂停应用程序的执行,可能导致较长的停顿时间。对于对停顿时间要求较高的应用,Serial收集器可能不合适。
  3. 无法与并发回收配合使用:Serial收集器无法与并发回收器(如CMS或G1)配合使用,只能在停顿时间允许的情况下进行垃圾回收,限制了应用的并发能力。
  4. 不适用于大型应用:由于Serial收集器是单线程的,对于大型应用程序或需要处理大量数据的应用,其吞吐量可能无法满足需求。

        可以看出一款单线程的垃圾回收器产品的弊端是多么明显,因此针对此弊端而诞生的回收器——ParNew / Serial Old收集器 出现了

7、ParNew / Serial Old收集器

优点:

  1. 并行垃圾回收:ParNew收集器使用多线程进行新生代的垃圾回收,可以充分利用多核处理器的优势,提高垃圾回收的效率。
  2. 低停顿时间:由于使用多线程进行垃圾回收,ParNew收集器能够在一定程度上减少停顿时间,适用于对停顿时间要求较高的应用场景。
  3. 较高的吞吐量:ParNew收集器的并行性可以提高垃圾回收的吞吐量,适用于对吞吐量要求较高的应用场景。

缺点:

  1. 线程同步开销:由于ParNew收集器使用多线程进行垃圾回收,需要进行线程同步操作,可能带来一定的开销。
  2. 老年代单线程:Serial Old收集器作为老年代的垃圾回收器,使用单线程进行垃圾回收,无法充分利用多核处理器的优势。

即使这样,老年代的垃圾回收还是单线程的。对此又研发了新的垃圾回收器——Parallel Scavenge / Parallel Old收集器 

8、Parallel Scavenge / Parallel Old收集器

优点:

  1. 高吞吐量:Parallel Scavenge/Parallel Old收集器以提高应用程序的吞吐量为目标,适用于对系统吞吐量要求较高的场景。通过并行垃圾回收和利用多核处理器的优势,可以在较短的时间内完成垃圾回收,减少应用程序的等待时间,提高整体吞吐量。
  2. 并行垃圾回收:Parallel Scavenge/Parallel Old收集器使用多线程进行垃圾回收,能够充分利用多核处理器的优势,提高垃圾回收的效率。通过并行处理,可以在更短的时间内完成垃圾回收操作。
  3. 自适应调节:Parallel Scavenge/Parallel Old收集器具有自适应调节的特性,可以根据应用程序的运行情况动态调整垃圾回收的策略和参数。这样可以在不同的工作负载下提供更好的性能和吞吐量。

缺点:

  1. 停顿时间较长:由于Parallel Scavenge/Parallel Old收集器以提高吞吐量为目标,相对于其他低延迟的垃圾回收器,其停顿时间可能会较长。这对于对停顿时间要求较高的应用场景可能不太适合。
  2. 较高的系统资源消耗:Parallel Scavenge/Parallel Old收集器使用多线程进行垃圾回收,需要消耗较多的系统资源,包括CPU和内存。在资源有限的环境下,可能会影响应用程序的正常运行。

吞吐量问题解决了,但是由stop the world所引起的停顿时间长问题还是没有解决,因此又出现了CMS收集器

9、CMS收集器(全名:Concurrent Mark Sweep)

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的并发垃圾回收器。

优点:

  1. 低停顿时间:CMS收集器通过在垃圾回收过程中与应用程序并发执行,尽量减少了应用程序的停顿时间。它使用了并发标记和并发清除的算法,在大部分时间内与应用程序并发工作,从而减少了垃圾回收对应用程序的影响,适用于对停顿时间要求较高的应用场景。
  2. 垃圾回收线程与应用程序线程并发执行:CMS收集器使用多个垃圾回收线程与应用程序线程并发执行,减少了垃圾回收线程与应用程序线程的竞争,提高了垃圾回收的效率和吞吐量。
  3. 适用于大内存堆:CMS收集器在处理大内存堆时表现良好,因为它在垃圾回收过程中采用了增量和部分并发的方式,不需要对整个堆进行全局暂停,减少了停顿时间的影响。

缺点:

  1. CPU资源消耗较高:由于CMS收集器在垃圾回收过程中与应用程序并发执行,需要消耗较多的CPU资源。这可能导致在高负载情况下,垃圾回收线程和应用程序线程之间的竞争增加,影响应用程序的性能。
  2. 需要更多的内存空间:CMS收集器使用空闲列表(Free List)来记录可回收对象,这会占用一部分堆空间。而且由于并发标记和并发清除的算法,CMS收集器在执行过程中需要维护一些额外的数据结构,这也会占用一定的内存空间。
  3. 碎片问题:CMS收集器使用了并发清除算法,清除过程中会产生内存碎片。这可能导致当应用程序需要分配大对象时,无法找到足够连续的内存空间,进而触发Full GC(全局垃圾回收),导致较长的停顿时间。

        CMS收集器虽然在一定程度上降低了垃圾回收的停顿时间,但仍然存在全局暂停(Stop-The-World)的情况,尤其在进行并发标记和并发清除时。这些全局暂停可能会对应用程序的响应性产生影响。而在面对高负载或极端场景时,可能会出现由于CPU资源竞争等因素导致的性能下降情况。因此出现了G1收集器。

10、G1收集器(全名:Garbage-First)

        G1(Garbage-First)收集器是一种面向服务端应用程序的垃圾回收器,它通过使用分区(Region)的方式,可以将垃圾回收的停顿时间更加可控,使得停顿时间更加均匀分布,降低了对应用程序的影响。在面对高负载或极端场景时,通过使用多个并行垃圾回收线程和更好的内存管理策略,可以提供更稳定和可预测的性能,尤其在大内存堆和多核处理器的环境下表现更好。

优点:

  1. 可预测的停顿时间:G1收集器通过将堆划分为多个固定大小的区域(Region),并采用增量和并发的方式进行垃圾回收,从而实现可预测的停顿时间。它会根据用户设置的停顿时间目标(Pause Time Goal)来动态地调整回收策略,尽量保持垃圾回收的停顿时间在可接受的范围内。

  2. 内存整理和碎片处理:G1收集器会在后台进行部分的内存整理和压缩操作,以减少内存碎片的产生。它采用了分代的思想,优先回收垃圾较多的区域,从而提高了内存的利用率。

  3. 并行和并发执行:G1收集器在垃圾回收过程中使用了多个并行垃圾回收线程,同时还利用多核处理器的优势进行并发标记和并发清理,以提高垃圾回收的效率和吞吐量。

  4. 可控的内存回收:G1收集器根据应用程序的需求,可以设定目标的垃圾回收时间。它会根据垃圾回收的成本和堆的使用情况,智能地选择回收的区域和回收的时间点,以达到最佳的吞吐量和停顿时间的平衡。

缺点:

  1. 初始标记和最终标记的停顿时间:G1收集器在执行初始标记(Initial Mark)和最终标记(Final Remark)时,需要进行全局的垃圾回收,因此会有一定的停顿时间。尽管这两个阶段的停顿时间通常较短,但仍可能对某些对停顿时间要求极高的应用程序产生影响。

  2. 需要更多的系统资源:相比于其他垃圾回收器,G1收集器需要更多的系统资源,包括CPU和内存。尤其在大堆和高负载的情况下,G1收集器可能需要更多的CPU资源来执行垃圾回收操作。

11、ZGC收集器(全名:Z Garbage Collector)

ZGC(Z Garbage Collector)是一种面向大内存堆和低延迟的垃圾回收器,它具有以下优点和一些考虑的缺点。

优点:

  1. 低停顿时间:ZGC的主要优势是在控制垃圾回收停顿时间方面。它采用了并发标记-整理算法,在与应用程序并发执行的情况下进行垃圾回收操作,极大地减少了全局停顿的时间。通常,ZGC的停顿时间保持在10ms以内(jdk1.6之后的停顿时间已经控制到1ms以内),对于需要高响应性和低延迟的应用程序非常有利。

  2. 分代压缩:ZGC使用了压缩指针和位图等技术来追踪对象的存活状态,从而减少了垃圾回收器的内存占用。它能够有效地处理大内存堆,并减少垃圾回收器本身的开销。

  3. 可扩展性:ZGC能够在多核处理器上运行,并利用多线程来并发执行垃圾回收操作,以提高垃圾回收的吞吐量和性能。

  4. 适应动态环境:ZGC在设计上考虑了应用程序的动态变化。它能够动态调整回收策略和内存布局,以适应应用程序的变化和垃圾回收的需求。

缺点:

  1. 垃圾回收性能:相对于一些其他垃圾回收器,如G1收集器,ZGC在整体垃圾回收性能方面可能略低。这是因为ZGC的主要关注点是低延迟,而不是最大化吞吐量。在某些高负载情况下,ZGC可能会牺牲一些吞吐量来实现低停顿时间。

  2. 初始标记时间:ZGC在执行垃圾回收的初始标记阶段会有一个全局停顿时间,用于标记根对象和直接可达的对象。虽然这个停顿时间通常较短,但在某些应用场景中仍可能对性能产生一定影响。

  3. 内存压缩:ZGC的压缩阶段可能会引起更长的停顿时间。在需要压缩内存的情况下,ZGC会执行更大的全局停顿以整理内存,并且在这个过程中可能会有更高的延迟。

总结

        影响垃圾回收的因素之一 ——"Stop-the-world"(停止一切)是一种垃圾回收过程中的一种现象,它指的是在进行垃圾回收时,应用程序的执行被临时暂停或停止。停止一切的目的是为了确保垃圾回收器能够安全地操作内存,并保证对象的一致性。

垃圾回收过程中会发生停止一切的情况的原因有多种,其中包括:

  1. 标记阶段:在标记-清除或标记-整理算法中,垃圾回收器需要标记哪些对象是存活的,而这个过程需要遍历对象图,并标记根对象及其可达对象。在这个标记阶段,为了保证对象图的一致性,需要停止应用程序的执行。

  2. 并发阶段初始标记:某些垃圾回收器采用了并发标记-整理算法,在并发标记阶段的初始标记阶段需要标记根对象和直接可达对象。为了确保标记的准确性,需要在这个阶段停止应用程序的执行。

  3. 内存整理:某些垃圾回收器(如标记-整理算法)在回收过程中需要对内存进行整理,将存活的对象整理到一端,以便回收未使用的内存。在这个整理阶段,需要停止应用程序的执行。

垃圾收集器使用场景用途
Serial小型应用或测试环境,注重简单和可预测的垃圾回收单线程的小型应用、开发和测试环境、桌面应用程序
ParNew多核处理器环境,强调吞吐量Web服务器、后端应用程序、具有多核处理器的中小型应用、或与CMS搭配使用
Parallel Scavenge专注于吞吐量和整体性能,对停顿时间要求不敏感数据处理应用、科学计算、需要最大化吞吐量而不太关心停顿时间的高负载应用
Serial Old小型应用或测试环境,注重简单和可预测的垃圾回收单线程的小型应用、开发和测试环境
Parallel Old多核处理器环境,强调吞吐量和整体性能Web服务器、后端应用程序、具有多核处理器的中小型应用
Serial / Serial Old单线程环境,对停顿时间要求不高,堆内存较小个人电脑上运行的简单Java应用、小型服务器上的简单Web应用、嵌入式系统
ParNew / Serial Old多线程环境,对停顿时间要求不高,以及与CMS配合使用大部分客户端应用、Web应用服务器,中小型企业应用
Parallel Scavenge / Parallel Old多核环境,对吞吐量要求高,注重整体性能而非低延迟,堆内存较大数据分析应用、科学计算应用、大型企业应用
CMS多核环境,对停顿时间要求较低,以及与ParNew配合使用,注重减少全局停顿时间大型企业应用、Web应用服务器、需要快速响应的实时系统
G1大内存堆环境,对停顿时间要求较低,高吞吐量,注重整体性能,需要更可控的垃圾回收行为大型企业应用、高性能计算、需要可预测停顿时间的实时系统
ZGC大内存堆环境,对停顿时间要求极低,注重低延迟,需要高吞吐量,对内存占用敏感大规模互联网应用、云计算环境、需要处理大内存的实时系统
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青旬_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值