为什么Concurrent Mark Sweep被弃用了?


作为JEP-291的一部分,Java Development Kit 9已经弃用了流行的Concurrent Mark Sweep垃圾收集算法。这一决定既减少了垃圾收集(GC)代码的维护负担,又加速了新的开发。
因此,如果在从Java 9或更高版本启动应用程序中,使用-XX:+ UseConcMarkSweepGC  参数激活并行标记扫描GC算法,您将看到以下警告:

Java HotSpot(TM) 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release.
Java HotSpot(TM)64位服务器VM警告:选项UseConcMarkSweepGC在9.0版中已弃用,可能会在将来的版本中删除。

如果要携带很多行李,特别是在Java代码中,你就很难继续前进。这正是导致Concurrent Mark Sweep功能消亡的原因。它是一种高度可配置的复杂算法,为Java开发工具包(JDK)中的GC代码库增加了许多复杂性。但是,只有当JDK开发团队可以简化GC代码库时,他们才能在GC领域加速和创新。

让我们探讨可以传递给每个GC算法的Java虚拟机(JVM)参数的数量,以证明它们有多复杂:

  • 一共有 50个参数
  • Parallel: 6
  • CMS: 72
  • G1: 26
  • ZGC: 8

有大约50个与GC相关的参数可以传递给任何JVM。除了这50个参数之外,CMS单独可以传递72个额外的参数,这比任何其他GC算法都要大得多。这种增加为JDK团队增加了显着的编码复杂性,以支持所有这些参数。
如果您目前使用CMS作为GC算法,您有哪些选择?
三个选择是:
  1. 切换到G1 GC算法
  2. 切换到Z GC算法(JDK 11,12中的早期访问)
  3. 继续使用CMS,并处理弃用警告

切换到G1 GC算法
G1 GC已成为自Java 9以来的默认GC算法,您可以安全地考虑将应用程序移至此算法。与Concurrent Mark Sweep相比,它可以提供更好的性能特性,并且调整此算法要容易得多,因为它包含的参数数量较少。此外,它还提供了从内存中消除重复字符串的选项。如果您可以消除这些重复的字符串,它可以帮助您减少总体内存占用量。


切换到Z GC算法
Z GC是一个可扩展的低延迟垃圾收集器,其主要目标是使GC暂停时间小于10毫秒。Z GC算法在Java 11和12中早期版本中都可用,因此如果您的应用程序在其中一个版本上运行,您可以将其视为并行标记扫描替代方案。

继续使用Concurrent Mark Sweep
对于某些应用,与G1 GC算法相比,Concurrent Mark Sweet可提供更好的结果,即使经过大量调整也是如此。如果您已经探索了替代方案,并且看到Concurrent Mark Sweep为您的应用程序提供了最佳结果,那么您应该坚持使用当前的GC算法。

有关在OpenJDK JDK9-dev邮件列表中保持Concurrent Mark Sweep活着的讨论,所以它可能不会永远消失。20年前在Java 1.1中弃用的某些功能和API仍在现代应用程序中使用,这意味着   弃用并不总是最终的结束。您可以继续在Concurrent Mark Sweep上运行,但请注意,它可能会在将来的任何版本中完全删除
请注意,每个应用程序都是独一无二的,并且不会受到关于GC调整和调整的期刊和其他文献的影响。当您设置新的GC设置时,您应该完成全面测试,表示基准性能特征并研究关键性能指标以做出明智的决策。​​​​​​​