JDK 11 之后的运行时更新 - Java 小酌

自 2018 年 9 月发布 JDK 11 以来,JDK 已进行了多项运行时更改,以提高性能并帮助解决常见问题。本文介绍了在此期间添加到 JDK 中的一些关键更改。

类数据共享更新

类数据共享 (CDS) 可追溯到 JDK 5。CDS 使用包含预处理类数据的共享存档。如果存在,JVM 可以从共享存档加载,从而提高启动性能。共享存档还会进行内存映射,当多个 JVM 在同一主机上运行时,它们都可以从同一共享存档中读取,从而减少内存使用量。

默认 CDS 存档

在 JDK 12 之前,Java 开发人员必须在非 Windows 平台上手动创建共享存档。JEP 314 在 JDK 12 中解决了这个问题,因为包含核心 JDK 类的共享存档现在包含在所有 JDK 映像中。

动态 CDS 存档

在 JDK 10 中,CDS 已扩展到涵盖应用程序类 AppCDS。AppCDS 允许 Java 开发人员创建包含其编写的应用程序中的类的共享存档。这将使 CDS 即使在更重要的应用程序中也能保持相关性和有益。最初,创建应用程序的共享存档是一个两步过程。用户需要运行应用程序以创建类列表,并且需要第二次运行才能基于先前创建的类列表创建共享存档。

JDK 13 中的 JEP 350 使用 VM 标志 -XX:ArchiveClassesAtExit=<shared archive> 将创建共享存档的过程简化为一个步骤。

有用的 NullPointerException

NullPointerException 是所有 Java 开发人员的祸根。最糟糕的情况是当 NullPointerException 发生在可能有多个引用类型为 null 的行上!在 JDK 14 中添加的 JEP 358,并在 JDK 15 中设为默认值,允许 JVM 精确描述哪个变量为 null。可以在此处查看新 NullPointerException 消息的示例

Exception in thread "main" java.lang.NullPointerException: 
        Cannot assign field "i" because "a" is null
    at Prog.main(Prog.java:5)

注意:此功能会带来一些性能开销,并且 JVM 如何打印消息可能存在一些安全问题。可以使用 -XX:-ShowCodeDetailsInExceptionMessages 禁用有用的 NullPointerException。

ZGC

ZGC 是对 Java 中垃圾回收的彻底重新设计。ZGC 最初作为 JDK 11 中的实验性功能引入(JEP 333)。在 JDK 15 中,JEP 377 将 ZGC 指定为产品功能。

ZGC 的设计目标是低延迟,最初的目标是暂停时间低于 10 毫秒,而截至 JDK 16,现在已低于 1 毫秒,并且能够扩展到多 TB 的堆大小(16 TB)。G1 垃圾收集器仍然是默认的 GC;可以使用 VM 标志启用 ZGC:-XX:+UseZGC

性能更新

JDK 的每次发布都会在许多因素上看到许多性能改进;启动、吞吐量、延迟、内存使用情况等。其中大多数更改不会提升到 JEP 的级别。尽管如此,在许多版本之后,所有这些更改的综合效果开始变得显着。

由于每个应用程序、系统架构和业务需求都不同,因此无法具体预测将运行时升级到最新 JDK 后会带来哪些性能改进,但如果在 JDK 11 或更早版本上,则好处应该是可衡量的。

要了解应用程序如何从升级运行时中受益,请使用 JDK Flight Recorder (JFR) 等工具对其进行分析,以详细分析运行时 JVM 和应用程序中发生的情况。这还有助于追踪因更新运行时而导致的任何问题。

其他阅读材料

编码愉快!