JavaRush /Java 博客 /Random-ZH /喝咖啡休息#210。您应该了解的 Java 中所有类型的垃圾收集器

喝咖啡休息#210。您应该了解的 Java 中所有类型的垃圾收集器

已在 Random-ZH 群组中发布
来源:Hackernoon 通过这篇文章,您将了解 Java 开发中使用的每种类型的垃圾收集器的优点和缺点。 喝咖啡休息#210。 您应该了解的 Java 中所有类型的垃圾收集器 - 1关于垃圾收集器(GC)的问题几乎在每次采访中都能听到。因此,我决定使用我最喜欢的原则(简短而简单)收集有关它们的所有必要信息。首先,让我们从 CG 的目的以及为什么我们需要多种类型的垃圾收集器开始。在像C这样的语言中,我们需要在内存中存储对象信息并编写大量样板代码来释放该内存。当然,内存泄漏在此类程序中很常见。Java 使用垃圾收集器解决内存泄漏问题。作为开发人员,您应该知道最好使用哪种垃圾收集器。很大程度上取决于程序的运行位置和方式。它可能运行在较弱的硬件上或具有大量对象,或者您的程序必须非常快。根据这些条件,您应该调整垃圾收集器以获得所需的性能。那么,让我们开始吧。

JVM如何处理内存

Java虚拟机(JVM)将内存分为两个区域:堆(存储应用程序数据)和非堆(存储程序代码和其他数据)。让我们把注意力转向堆区域。这是我们的程序创建新对象的地方。所有垃圾收集器都基于许多程序使用短暂对象的事实。也就是说,这些对象被创建,然后完成其功能并且不再需要。大多数此类对象。但有些物体的寿命要长得多,甚至可能在整个程序期间都是如此。这就是将对象分为年轻代和老年代的想法产生的地方。我们需要经常检查年轻一代。事实上,垃圾收集过程分为轻微清理(仅影响年轻一代)和完全清理(可能影响两代)。请记住,垃圾收集器是一个程序。它需要计算机的时间和资源才能工作。这也影响了我们的应用。它有何影响?例如,为了执行垃圾收集,JVM 会暂停我们的应用程序。这称为“世界停止”(STW) 暂停。在此期间,所有应用程序线程都被挂起。但里面的应用程序完全不知道这一点。对于应用程序来说,时间是均匀流动的。为什么情况这么糟糕?想象一下,您正在编写某种交换应用程序或飞机自动驾驶仪应用程序。您的应用程序可能会进入休眠状态一秒钟,然后问题的性质可能会发生巨大变化。也就是说,暂停对于每个垃圾收集器来说都是一个重要的参数。垃圾收集器的下一个基本属性是收集垃圾所花费的总时间与程序总执行时间的关系。这意味着什么以及为什么如此重要?我们可以选择一种具有许多小暂停的算法,而不是一个大的“Stop-The-World”阶段。短暂的休息是更好的选择,但没有什么是免费的。在这种情况下,我们通过增加程序的总执行时间来付费。我们也必须考虑到这一点。下一个参数是硬件资源量。每个收集器都需要内存来存储对象信息和处理器来执行清理。最后一个参数是速度。垃圾收集效率是指垃圾收集器 (GC) 回收程序不再使用的内存的速度和效率。所有这些参数都会影响算法,算法可以在消耗最少资源的同时尽快释放内存。让我们看一下我们可以使用的垃圾收集器。对于面试,您需要了解前五个。另外两个要困难得多。

串行GC

Serial GC 是 Java 虚拟机的垃圾收集器,自 Java 诞生以来就一直在使用。它对于堆较小且运行在功能较弱的机器上的程序很有用。该垃圾收集器将堆划分为多个区域,其中包括 Eden 和 Survivor。Eden 区域是大多数对象最初分配内存的池。Survivor 是一个池,包含在 Eden 区域的垃圾回收中幸存下来的对象。当堆填满时,对象会在 Eden 区和 Survivor 区之间移动。JVM 不断监视对象向 Survivor 区域的移动,并为此类移动的次数选择适当的阈值,之后将对象移动到 Tenured 区域。当 Tenured 区域中没有足够的空间时,完整垃圾收集将接管,对两代对象进行处理。 这种垃圾收集器的主要优点是其资源需求低,因此低功耗处理器足以执行收集。Serial GC 的主要缺点是垃圾收集期间的长时间暂停,尤其是当涉及大量数据时。

平行CG

并行垃圾收集器(Parallel CG)类似于顺序构造函数。它包括一些任务的并行处理和自动调整性能设置的能力。并行 GC 是一种基于串行 GC 思想的 Java 虚拟机垃圾收集器,但增加了并行性和智能性。如果计算机有多个处理器核心,旧版本的 JVM 会自动选择并行 GC。这里的堆被划分为与 Serial GC 中相同的区域 - Eden、Survivor 0、Survivor 1 和 Old Gen (Tenured)。然而,多个线程并行参与垃圾收集,收集器可以调整到所需的性能参数。每个收集器线程都有一个需要清除的内存区域。并行 GC 还具有旨在实现所需垃圾收集效率的设置。收集器使用以前垃圾收集的统计信息来调整未来收集的性能设置。并行 GC 提供性能参数的自动调整和较低的构建暂停时间,但有一个小缺点,即一些内存碎片。它适用于大多数应用程序,但对于更复杂的程序,最好选择更高级的垃圾收集器实现。 优点:在许多情况下比 Serial GC 更快。具有良好的速度。缺点:消耗更多资源,暂停时间可能会很长,但我们可以调整 Stop-The-World 的最大暂停时间。

并发标记清除

并发标记清除 (CMS) 垃圾收集器旨在通过与应用程序线程同时运行一些垃圾收集任务来减少最大暂停长度。这种垃圾收集器适合管理内存中的大量数据。并发标记清除 (CMS) 是 Java 虚拟机 (JVM) 中并行 GC 的替代方案。它适用于需要访问多个处理器内核并对 Stop-The-World 暂停敏感的应用程序。CMS 与主程序并行执行垃圾收集步骤,这使得它可以不间断地运行。它使用与串行和并行收集器相同的内存组织,但在运行老年代清除之前不会等待 Tenured 区域被填充。相反,它在后台运行并尝试保持 Tenured 区域的紧凑。并发标记清除从初始标记阶段开始,该阶段会短暂停止应用程序的主线程并标记可从根访问的所有对象。然后应用程序的主线程恢复,CMS 开始搜索可通过标记根对象的链接访问的所有活动对象。标记完所有存活对象后,收集器会清除多个并行线程中死亡对象的内存。CMS 的优点之一是它专注于最大限度地减少停机时间,这对于许多应用程序至关重要。然而,它需要牺牲CPU资源和整体带宽。另外,CMS不会压缩老年代中的对象,这会导致碎片。由于可能的并行模式故障而导致的长时间暂停可能会令人不愉快(尽管这种情况并不经常发生)。如果有足够的内存,CMS 可以避免此类暂停。 优点:快。有短暂的“世界静止”停顿。缺点:消耗较多内存;如果内存不足,某些停顿可能会很长。如果应用程序创建了很多对象,那就不太好。

垃圾优先

垃圾优先 (G1) 被认为是 CMS 的替代方案,特别是对于在多处理器服务器上运行并管理大型数据集的服务器应用程序。G1 垃圾收集器将内存转换为多个同等大小的区域,但巨大区域除外(通过合并常规区域以容纳大量对象而创建)。区域不必连续组织,并且可以改变它们的世代隶属关系。定期对年轻一代进行小型清除,并将对象移动到幸存者区域或将其升级到老一代并将其转移到终身。仅在需要避免超过所需时间的区域进行清洁。收集者自己预测并选择垃圾量最多的区域进行清洁。完整扫描使用标记循环来创建与主应用程序并行运行的活动对象列表。标记周期结束后,G1 切换到运行混合清除,这会将较旧的生成区域添加到要清除的年轻生成区域集中。G1 垃圾收集器被认为在预测暂停大小方面比 CMS 收集器更准确,并且可以更好地随时间分布垃圾收集,以防止应用程序长时间停机,尤其是在堆大小较大的情况下。它也不像 CMS 收集器那样产生内存碎片。然而,G1收集器需要更多的CPU资源来与主程序并行运行,这降低了应用程序的吞吐量。 优点:比 CMS 更好用。停顿时间较短。缺点:消耗更多的CPU资源。此外,如果我们有许多相当大的对象(超过 500 KB),它会消耗更多内存,因为它将这些对象放在一个区域中(1-32 MB)。

埃普西隆气相色谱仪

Epsilon GC 专为不需要垃圾回收的情况而设计。它不执行垃圾收集,而是使用 TLAB(线程本地分配缓冲区)来分配新对象 - 各个线程从堆中请求的小内存缓冲区。不适合缓冲区的巨大对象专门为自己请求内存块。当 Epsilon GC 耗尽资源时,会生成 OutOfMemoryError 并且进程终止。Epsilon GC 的优点包括较低的资源需求和更快的内存分配,适用于在启动时创建所需的所有对象或运行不使用所有已分配内存的短期应用程序的应用程序。Epsilon GC 还可以帮助分析其他垃圾收集器添加到您的应用程序中的资源需求。 优点:非常快。缺点:不清除对象:) 接下来的两个收集器是同类收集器中最先进的,但也是最复杂的。因此,我们将简要考虑它们。

中关村

即使在处理海量数据时,ZGC 也能保持亚毫秒级的延迟。ZGC 是 Oracle 为 Java 开发的垃圾收集器,旨在在处理大型堆(高达 16 TB)时提供高吞吐量和低延迟。ZGC基于虚拟内存原理,在垃圾收集过程中使用不同的颜色标记来跟踪对象的状态。 优点:即使在大型堆上,暂停也少于一毫秒,这对于需要较短查询处理时间的应用程序非常有用。它适用于具有良好吞吐量的非常大的堆。ZGC可以在垃圾收集期间压缩堆内存。缺点:CPU 使用率高且性能要求高,这可能会减慢应用程序的启动时间。

谢南多厄 G.C.

Shenandoah GC 是另一种垃圾收集器,无论堆大小如何,都会短暂暂停。这个垃圾收集器是由红帽开发的。它旨在最大限度地减少应用程序在垃圾收集上花费的时间。与 ZGC 一样,它是一个并行收集器,这意味着它在应用程序运行时运行,从而最大限度地减少暂停。Shenandoah GC 在垃圾收集期间使用“前向指针”来移动对象。它还具有一种称为“负载屏障去除”的技术来提高性能。 优点:Shenandoah GC 可以实现较短的暂停时间,通常小于 10 毫秒,即使对于大量堆也是如此。良好的吞吐量。缺点:处理器负载高,难以在重负载下工作。

结论

垃圾收集器是编程中最困难的任务之一。新的发展正在朝着这个方向不断进行。虽然程序员很少调整 GC,但您仍然需要至少了解垃圾收集工具的工作原理。
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION