JDK 18修复了三个重要功能 - malloc


现在让我们谈谈 JDK 18 中的新功能(从 ZGC 的角度来看)。

字符串重复数据删除
字符串重复数据删除是一个 JVM 特性 ( -XX:+UseStringDeduplication),它已经存在了很长一段时间。它通过自动删除支持 String 对象的相同字符数组来帮助减少 Java 堆内存使用。例如,如果堆上存在两个 String 对象,并且它们都指向一个包含字符“Java”的后备数组,那么其中一个 String 对象将被修改,以便两个 String 对象指向同一个数组,而另一个数组将变得无法访问并受到垃圾收集。这可以帮助一些应用程序减少相当多的堆内存使用量,因为 String 对象可以占用 Java 堆的重要部分,并且在这些对象中查找重复项是相当普遍的。

类的卸载问题得到修正
我们在ZGC邮件列表中收到一份关于性能问题的报告。结果发现这是一个10年前的错误,可以追溯到PermGen的删除。

因此,大约10年前,移除PermGen的补丁对一个处理Inline Cache清理的函数做了一些修改。Inline Cache是一种投机性的优化技术,由JVM用来加快Java中的方法调用速度。当GC卸载未使用的类和编译的方法时,一些Inline Cache需要被清理,以便它们不再引用任何未加载的实体。

事实证明,这个补丁包含了一个小而重要的编辑错误,即缩进和作用域被混淆了。光看补丁很难发现这个错误,因为有问题的代码也被移动了。这个错误导致了一些内联缓存被错误地清理了。然而,这种不正确的清理并没有导致任何明显的问题,比如JVM崩溃。相反,它引起了一个恶性循环,GC和Java线程在如何清理这些缓存方面存在分歧,并为之争吵。最终的结果是,在某些情况下,类的卸载可能需要很长的时间才能完成。由于这个问题的根本原因是GC和并发运行的Java线程之间的不良互动,所以它只影响到做并发类卸载的GC(如ZGC)。做 "停止世界 "类卸载的GC(如SerialGC、ParallelGC和G1GC)不受影响,因为这种不良的互动永远不会出现,因为Java线程从来不与GC同时运行。

幸运的是,一旦这个问题被发现,修复工作就很简单了。如果你对更多的细节感兴趣,你可以在相应的拉动请求中阅读所有关于它的内容。

Linux/PowerPC支持
早在2013年,也就是在ZGC出现之前,JEP 175就已经创建了,以便为OpenJDK带来Linux/PowerPC(以及AIX/PowerPC)支持。最初的移植是作为JDK 8u20的一部分发货的,并一直保持到现在。支持这一平台的努力从一开始就得到了我们在SAP的朋友的资助。

因此,当听到也是SAP提供了使ZGC在Linux/PowerPC上可用的补丁时,可能不会感到惊讶。增加对新的CPU架构的支持,主要是在解释器和两个JIT编译器中实现ZGC的各种障碍(负载障碍、nmethod进入障碍和堆栈水印障碍)。该补丁大约有1200行代码。

从JDK 18开始,ZGC现在可以在以下平台上运行(更多细节见此表)。

  • Linux/x64
  • Linux/AArch64
  • Linux/PowerPC
  • macOS/x64
  • macOS/AArch64
  • Windows/x64
  • Windows/AArch64

总结

  • 现在支持JVM选项-XX:+UseStringDeduplication。这个功能(默认情况下是禁用的)告诉ZGC寻找并重复利用相同的字符数组来支持String对象,以减少整体堆内存的使用。
  • 修正了一个10年前的错误,该错误有时会导致类的卸载时间非常长。
  • ZGC现在可以在Linux/PowerPC上运行,这要感谢SAP的人。