22.2.0

(2022-07-26)

平台更新

  • 通过将基本二进制文件的大小减少近一半,改进了 GraalVM 的打包体验。JavaScript、LLVM 运行时和 VisualVM 现在已从主软件包中解耦,并作为独立的可安装组件发布。例如,GraalVM Community Linux 发行版的大小从约 430 MB 降至约 250 MB。这使得 GraalVM 更加模块化,在您仅添加所需支持时提供相同的 RPM 般体验。
  • Native Image 组件的大小有所增加,因为必要的运行时组件 (Substrate VM) 和静态库 (由 Substrate VM 使用) 现在是 Native Image 可安装包的一部分。
  • 改进了 Apple Silicon 支持
    • 发布了适用于 Apple Silicon (AArch64 架构) 的 GraalVM Enterprise 发行版。此支持为实验性功能。
    • 扩展了现有适用于 Apple Silicon 的 GraalVM Community 发行版中支持的 GraalVM 功能。您现在可以选择安装 Native Image、LLVM 工具链、Java on Truffle,以及 JavaScript、Ruby、WebAssembly 的语言运行时。
  • GraalVM 将不再支持某些较旧的 Linux AMD64 发行版。它现在是基于 glibc 2.17 (而非 2.12) 构建的,因此可能无法在 Oracle Linux 6 或其他 RHEL 6 衍生版上运行。

  • GraalVM Community Edition 所基于的 OpenJDK 版本已更新至
  • GraalVM Enterprise Edition 所基于的 Oracle JDK 版本已更新至

Java 和编译器更新

  • 改进了 GraalVM Community Edition 中 JIT 编译器 (Graal) 的 RSS 内存使用。当编译空闲时,libgraal 所使用的内存现在会被回收。这减少了 JIT 在稳定状态 (几乎没有或没有编译发生) 下的 RSS 使用。要测量 Java 进程的 RSS 内存使用情况,您可以运行 ps aux --sort -rss。参见 JDK-8242440

  • 增强了针对计数循环的新型分条挖掘(Strip Mining)优化。此优化可以通过以下选项启用:-Dgraal.StripMineCountedLoops=true。分条挖掘优化将单个长时间运行的循环转换为一个嵌套循环,其中内部循环体在有界时间内运行。这允许您在外层循环中设置安全点,以减少安全点轮询的开销。通过为外层循环步长选择正确的值,您仍然可以确保合理的到达安全点延迟。后者对于 ZGC 和 Shenandoah 等低暂停时间收集器尤为重要。例如,此循环

      int checksum = 0;
              for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
                  checksum += i;
                  // safepoint_poll
              }
    

    将变为

      int checksum = 0;
      for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE - 1000; i += 1000) {
          for (int j = i; j < i + 1000; j++) {
              checksum += j;
          }
          // safepoint_poll
      }
      for (int i = Integer.MAX_VALUE - 1000; i < Integer.MAX_VALUE; i++) {
          checksum += i;
          // safepoint_poll
      }
    

    此优化增加了 Truffle 访客语言安全点的延迟。例如,新型分条挖掘优化消除了执行分配的计数循环中的 HotSpot 安全点(HotSpot 分配慢路径有一个安全点)。然而,这个与分配相关的安全点不会触发 Truffle 安全点。因此,Truffle 安全点延迟可能非常长。在这种情况下,新型分条挖掘优化可以将此类循环分解为条带,并为每个条带发出一次 Truffle 安全点轮询。

  • 在编译管道早期启用了除法节点的浮动和全局值编号,前提是已知它们不会陷入异常。这意味着如果常量除数证明不会抛出除以零异常,则常量除法操作可以进行公共子表达式消除并移出循环。参见 #3866

  • 在编译管道早期引入了固定节点的全局值编号优化。此功能默认禁用,但可以通过 -Dgraal.EarlyGVN=true 启用。此优化改进了需要复杂局部逃逸分析和展开优化才能优化掉包含复杂对象分配的常量循环的工作负载。此优化还可以通过在编译管道早期减小图的大小来加快 Native Image 构建时间,并通过折叠更多内存操作来加快生成的原生可执行文件本身的运行速度。

Native Image

  • 增强了 GraalVM Native Image 与第三方库的兼容性。Oracle GraalVM 团队与 Spring、Micronaut 和 Quarkus 团队合作创建了一个 GitHub 存储库,即 GraalVM Reachability Metadata Repository,这是一个集中式位置,为默认不支持 GraalVM Native Image 的库提供配置(可达性元数据)。此支持需要显式启用。例如,在 Gradle 中,您可以通过以下方式启用此存储库:
      graalvmNative {
          metadataRepository {
              enabled = true
          }
      }
    

    GraalVM Reachability Metadata Repository 允许用户共享和重用 Java 生态系统中最流行库的可达性元数据。请查阅文档以获取更多信息。

  • native-image 生成器现在默认在模块路径上运行。这是支持使用干净的模块化生成器构建基于模块的应用程序的长期工作的一部分。模块系统默认阻止直接访问 native-image 生成器的内部组件。应用程序和框架仍然可以使用常用的模块系统命令行选项提供命令行参数,以重新开放内部组件。目前,可以通过设置环境变量 USE_NATIVE_IMAGE_JAVA_PLATFORM_MODULE_SYSTEM=false 来启用运行 native-image 生成器的旧模式(但请注意,此模式将在未来版本中被删除,且无替代方案)。

  • 改进了 native-image 生成器的许多内部数据结构,以减少内存占用。这使得 Native Image 构建在内存受限的环境中(例如基于云的构建服务、GitHub ActionsDocker 容器)运行时更加健壮。现在许多大型应用程序在使用 2 GB Java 堆内存供 native-image 生成器使用时,都能成功构建。

  • 增加了对软件物料清单 (SBOM) 的支持。native-image 生成器可以选择性地将 SBOM 包含到原生可执行文件中,以帮助漏洞扫描器。目前支持 CycloneDX 格式。用户可以在编译期间使用 -H:IncludeSBOM=cyclonedx 选项将 CycloneDX SBOM 嵌入到原生可执行文件中。将压缩的 SBOM 嵌入到可执行文件后,您可以使用 Native Image Inspect 工具,通过以下命令提取压缩的 SBOM:$JAVA_HOME/bin/native-image-inspect --sbom <path_to_binary>。请查看文档以获取更多详细信息仅限 GraalVM Enterprise

  • 为字符串连接操作(包括 StringBuilder 操作)添加了一项新优化:它在连接过程中消除了临时内存缓冲区。仅限 GraalVM Enterprise

  • GraalVM Community Edition 现在支持在镜像运行时进行堆转储。此外,还引入了一个新的运行时选项 -XX:+DumpHeapAndExit,用于转储原生可执行文件的初始镜像堆。请查阅文档,了解如何转储原生可执行文件的初始堆

  • 改进了 Linux 上的调试支持:Dwarf 信息现在包含有关参数和局部变量的信息(由 Red Hat 贡献)。

  • 某些 Native Image 选项现在只能通过命令行提供,不再支持在 native-image.properties 文件中提供。这些选项也会在其他选项之前处理,以便它们正确预配置所有来自命令行和 native-image.properties 文件的其他选项。受影响的选项包括 --exclude-config--configurations-path--debug-attach--diagnostics-mode,以及所有用于打印帮助信息的选项。

  • 添加了一个新的运行时选项 -XX:+ExitOnOutOfMemoryError,它会在首次出现内存不足错误时中止原生可执行文件的执行。

  • 在镜像运行时增加了对 OperatingSystemMXBean 大多数方法的支持。

  • 注解类不再在镜像构建时强制初始化。像任何其他类一样,注解类现在可以在构建时或运行时通过相应的命令行选项 (--initialize-at-build-time--initialize-at-run-time) 或 Feature API 进行初始化。这解决了注解的传递依赖问题,包括注解使用的非注解类。参见Native Image 中的类初始化

多语言运行时

  • 引入了更新,将 GraalVM 支持的语言的纯解释器性能提高了 20-30%,并缩短了预热时间。
  • libgraal 中增加了对跨 Truffle 编译缓存编码图的支持,以加快部分求值。该缓存默认启用,可以通过 --engine.EncodedGraphCache 选项启用/禁用。此更新有助于缩短 HotSpot 上的编译时间。
  • 为 Truffle 解释器宿主编译实现了一个新的领域特定内联阶段,这提高了 GraalVM Native Image 的解释器性能。有关详细信息,请参阅解释器 Java 代码的宿主编译参考手册。

完整更新列表可在变更日志中找到。

JavaScript

  • JavaScript 支持现在已从 GraalVM 基础安装中解耦,可以通过以下命令轻松添加:gu install js
  • 改进了 JavaScript 与 Java 的互操作性:现在外部对象默认会被分配一个 JavaScript 原型,除非明确关闭。此功能以前在实验性选项 js.foreign-object-prototype 之后可用,现在已成为默认设置。以前,如果您在 JavaScript 代码中使用任何外部对象(例如 Java 数组),您可以通过索引操作符 [] 访问它。然而,该数组缺少 Array.prototype,因此无法轻松调用诸如 indexOfsort 之类的方法。通过此更改,外部对象将获得一个合适的 JavaScript 原型,并可以通过常规 JavaScript 函数进行“操作”。这为普通 Java 用户或GraalVM Polyglot API 用户增加了更多灵活性。
  • 扩展了 GraalVM JavaScript 中 Temporal 规范的实现,该规范提供了用于处理日期和时间的标准对象和函数。规范中的更改正在持续采纳中。Temporal 对象现在可以在适当的时候使用 Value API 的方法(例如 asDate())转换为兼容的 Java 对象。将 Java Temporal 对象与 JavaScript Temporal 方法结合使用的反向功能计划在未来版本中实现。

请查看项目变更日志

Ruby

  • 增加了对 macOS (Apple Silicon) 的 AArch64 发行版支持。
  • 通过更新 openssl gem,增加了对 OpenSSL 3.0.0 的支持。
  • 已更新至 Ruby 3.0.3。这 3 个 CVE 未影响 TruffleRuby,此更新旨在同步 stdlib 和 gem。
  • 实施了多项改进 GraalVM 上 Ruby 性能的更改
    • 重新实现了 Float#to_s 以提高性能。
    • 通过使 C 对象释放函数和其他终结器更轻量化,更新了引用处理。
    • 提高了 interned 字符串的 RSTRING_PTR 性能。
    • 启用了对 rb_scan_args_kw 使用的常量参数格式进行缓存。
  • 改进了与 CRuby 3.2 的兼容性:现在编译 C 扩展时使用 -Werror=implicit-function-declaration,以便在函数缺失时更清晰、更早地报告错误。

完整更改列表可在变更日志中找到。

Python

  • 更新至 HPy 0.0.4 版本,该版本增加了对已完成的 Kiwi HPy 移植、以及正在进行的 Matplotlib 和 NumPy 移植的支持。
  • 添加了一个实验性字节码解释器,以实现更快的启动和更好的解释器性能。可以通过 --python.EnableBytecodeInterpreter 选项切换使用先前的 AST 解释器或新的字节码解释器。

项目变更日志可在 GitHub 上查看。

R

  • 实现了 SET_GROWABLE_BITIS_GROWABLE C API 函数。这解决了 cpp11 0.2.6 包的安装问题。
  • 将 akima 包添加到“原生包”列表中,因此它默认由原生后端加载。

项目变更日志可在 GitHub 上查看。

LLVM 运行时

  • LLVM 运行时现在已从 GraalVM 基础安装中解耦,可以通过以下命令轻松添加:gu install llvm
  • LLVM 工具链已更新至 14.0.3 版本。
  • 增加了对 macOS (Apple Silicon) 的 AArch64 发行版支持。
  • 改进了对 POSIX 线程 (pthreads) 和托管执行模式的支持。在此模式下,不允许调用原生代码和访问原生内存。

Truffle 上的 Java

  • 增加了对 macOS (Apple Silicon) 的 AArch64 发行版支持。
  • 改进了类重新定义:增加了支持附加枚举常量。这使得 HotSwap 功能在调试会话期间运行时更改类时更加强大。请参阅使用 Java on Truffle 增强 HotSwap 功能指南。
  • 默认启用新的类层次结构分析。它提供访客代码中的类层次结构信息,并随着新类的加载而演变。

WebAssembly

  • 根据我们的基准测试,此版本在 GraalVM WebAssembly 实现方面有显著的性能提升
    • 内部 AST 内存占用改进 3.18 倍
    • 峰值性能改进 1.24 倍

多语言嵌入

  • 增加了在原生启动器或库中为每个 EngineContext 生成一个 native-image 隔离区的功能。此功能以前仅在 JVM 部署中受支持。仅限 GraalVM Enterprise
  • 增加了 Value.hasMetaParents()Value.getMetaParents() 方法,允许查找元对象的父级层次结构(例如,Java 类的超类或实现的接口)。
  • 增加了 HostAccess.Builder.allowAccessInheritance,用于继承接口或超类中显式导出的方法的访问权限,而非仅显式验证的方法实现(例如,通过 @HostAccess.Export)。
  • 增加了对映射到 java.util.List 的多语言值的 List#add 支持。

完整更改列表可在变更日志中找到。

Truffle 语言和工具实现

  • com.oracle.truffle.api.frame.Frame 增加了新的静态 API
    • 为基于索引的槽位实现了 FrameSlotKind 的一个新静态选项。使用此类型的帧槽位之后不能更改为其他类型。静态帧槽位可以同时持有一个原始值和一个对象值。静态帧槽位旨在用于变量类型预先已知且无需任何类型检查的情况(例如,在静态类型语言中)。
    • 静态帧槽位适用于变量类型预先已知且无需任何类型检查的情况(例如,在静态类型语言中)。
  • 静态对象模型也为 GraalVM Native Image 提供了基于字段存储的初步支持。
  • Truffle IGV 以日志级别 5 (-Dgraal.Dump=Truffle:5) 进行转储时,现在会在每个完全部分求值的方法之后转储图。这使得调试仅在部分求值期间可见的问题成为可能。

完整更新列表可在变更日志中找到。

工具

  • 通过我们的适用于 Java 的 GraalVM VS Code 扩展,改进了在 Windows 上构建原生镜像的功能。现在,Windows 10 上的 .\gradlew nativeBuild 在 x64 Native Tools Command Prompt 中运行。
  • GraalVM Updater 现在可以为 availablelistinfo 命令生成 JSON 输出,这使得其他工具(例如适用于 Java 的 GraalVM VS Code 扩展)能够更容易地以编程方式使用它。

联系我们