适用于 JDK 20.0.2 的 GraalVM

(2023-07-25)

这是 GraalVM 社区版 2023 年 7 月的关键补丁更新 (CPU)。它基于 OpenJDK CPU,并包含了作为该 CPU 一部分发布的所有 OpenJDK 安全修复、平台更新和一些 GraalVM 功能错误修复。这是一个完整的分发版,取代了之前发布的适用于 JDK 20.0.1 的 GraalVM 社区版。

  • 更新了 GraalVM 社区版构建所基于的 OpenJDK 版本至 20.0.2+9。请参阅OpenJDK 20 更新
  • Graal 编译器:更新了计数带状挖掘优化,以避免对溢出循环进行带状挖掘。
  • Native Image:修复了 jvmstat 性能数据初始化问题。
  • Native Image:修复了 JDK Flight Recorder (JFR) 事件常量池 ID。
  • Native Image:修复了 Native Image 中的用户体验问题。
  • Native Image:修复了构建报告中的分析结果问题。

适用于 JDK 20.0.1 的 GraalVM

(2023-06-13)

平台更新

  • 发布了基于 OpenJDK 20.0.1+8 的 GraalVM 社区版 for JDK 20。请参阅OpenJDK 20 更新
  • 简化了 GraalVM 包命名:其格式为 graalvm-community-jdk-<full java version>_<platform>-<arch>,例如:graalvm-community-jdk-20.0.1_macos-aarch64_bin.tar.gz

Java 和编译器更新

  • 新增了对 ZGC 垃圾收集器的支持,适用于需要低延迟或使用超大堆内存的工作负载。参见 #2149
  • 通过添加非投机模式,增强了乐观别名分析。(改进循环向量化。)某些代码形态以前仅在 JIT 中向量化,但在提前编译中不向量化。随着 Native Image 循环向量化的改进,这些代码形态的差异消失了,使得编译器能够向量化更多循环以实现更快的执行。
  • 改进了新型优化编译器阶段的日志记录:统一了日志记录和转储(例如,通过 JSON)优化决策的接口。优化阶段应使用 OptimizationLog 来记录转换。在 OptimizationLog.mdProfdiff.md 中阅读更多内容,了解如何在热编译中比较已执行的优化。
  • Ideal Graph Visualizer (IGV) 开源,以便第三方编译器和语言开发者更容易使用和贡献。更多信息请参见此处

请在更新日志中查看更多更新。

Native Image

打包和平台更新

  • Native Image 现在作为 GraalVM for JDK 20 的一部分提供,不再需要通过 gu install native-image 进行安装。更多信息请阅读此处
  • Native Image 现在可以在 Windows 上自动设置构建环境,如果它能在已知位置找到 Visual Studio 安装。因此,在 x64 Native Tools Command Prompt 中运行不再是必需条件。
  • 改进了 Linux 上 AWT 库的动态链接。Linux 上 AWT 库的静态链接一直是一个问题来源。动态链接避免了静态链接的缺陷,代价是失去了独立的可执行文件,但正如 Windows 上 AWT 支持所示,这是一个合理的权衡。链接器不应再因“jvm 多重定义”而失败,或在 Linux 上为 AWS/Swing 应用程序的链接步骤崩溃。
  • Jipher JCE,一个基于 OpenSSL 3.0 FIPS 实现的 Java 加密架构 (JCA) 提供程序,现在支持 GraalVM Native Image。建议在仅允许使用 FIPS 算法的环境中通过 Native Image 启用 Jipher。请参阅文档以开始使用。

新功能

  • 引入了一项新功能:按需从自包含的bundle构建原生可执行文件。新选项--bundle-create=<imagename>.nib会创建一个<imagename>.nib文件(一个构建bundle)和launch.output目录,与原生可执行文件同时生成。bundle文件,即<imagename>.nib,是一个常规的JAR文件,其中包含构建原生可执行文件(或原生共享库)所需的所有信息。与常规的native-image构建不同,此操作模式只接受单个*.nib*文件作为输入。在任何后续时间,如果使用相同版本的GraalVM,可以重新构建可执行文件,通过
    native-image --bundle-apply=.../path/to/launch.nib
    

    它将使用与初始构建相同的镜像参数、环境变量、系统属性、类路径和模块路径选项重新构建原生可执行文件。这是一种安全可靠的解决方案,可将构建所需的所有输入封装到一个文件中。在Native Image Bundles 参考手册中了解更多信息。

  • 改进了 Native Image 构建过程的内存占用。构建器现在会考虑可用内存,以在同一机器上运行许多其他进程时减少内存压力。在许多情况下,它还消耗更少的内存,因此也更不容易因内存不足错误而失败。同时,内存限制从 14GB 提高到 32GB。
  • Native Image 现在在 AMD64 上默认以 x86-64-v3 架构为目标,并提供了一个新的 -march 选项来指定目标兼容性。如果原生可执行文件部署在同一台机器或具有相同 CPU 功能的机器上,请使用 -march=compatibility 以获得最佳兼容性,或使用 -march=native 以获得最佳性能。要列出所有可用的机器类型,请使用 -march=list
  • 通过抛出特殊异常,改进了 Native Image 中缺失元数据的报告。Native Image 不区分缺失的可达性元数据和 Reflection API 抛出的异常。例如,当类不在类路径上或类的元数据不存在时抛出的 ClassNotFoundException。现在,Native Image 用户可以捕获元数据异常,并使用选项 -XX:ExitOnMissingMetadata 调试其程序,以确保所有元数据条目都是正确的。更多信息请阅读此处。这是一个实验性功能,默认未开启。
  • 在 Native Image 中引入了 Reflection 和 Resources 元数据的安全组合。例如,反射方法如 java.lang.Class#getDeclaredMethodsreturn 基于其他反射元素的可达性。添加新的元数据会使更多元素可达,并可能改变程序功能。得益于元数据优化的安全组合,native-image 构建器现在确保对 java.lang.Class 的每个反射调用都需要一个元数据条目。更多信息请阅读此处
  • 禁止不带参数的 --initialize-at-build-time 选项。作为临时解决方案,-H:+AllowDeprecatedInitializeAllClassesAtBuildTime 选项将此错误转换为警告。
  • 通过 LLVM 后端为 Native Image 添加了实验性的 RISC-V 模式。在此博客文章中阅读更多内容。
  • 改进了 Native Image 中的配置文件引导优化 (PGO)(PGO 在 GraalVM 社区版中不可用)
    • 配置文件引导优化现在有一个新的采样分析器,可以定期收集调用栈。使用选项 --pgo-sampling 开启采样分析器并收集调用栈。此数据将包含在 .iprof 文件中。构建 PGO 仪器化的可执行文件时,采样分析器默认开启(但可以使用选项 -H:-SamplingCollect 关闭)。要获得良好的配置文件并因此获得良好的峰值性能,您需要运行相关工作负载并充分预热应用程序。
    • 实现了上下文感知内联器 (CAI) 优化,该优化专门用于“热”代码中的采样配置文件,并投入更多优化精力到热编译单元。当为 PGO 构建优化镜像时,上下文感知内联器会自动开启(但可以使用选项 -H:-AOTInliner 关闭)。结果是可执行文件大小减小 2-7%,并提高了峰值性能。
    • 改进了配置文件合并并启用了预打包配置文件。
  • 增加了基于机器学习 (ML) 的配置文件推理。当配置文件被禁用时,Native Image 中的 Graal 编译器使用预训练的 ML 模型来推断控制分支的配置文件。然后,推断出的配置文件用于执行配置文件引导优化。在某些基准测试(如 Renaissance、Da Capo 和 Da Capo con Scala)中,与默认的 Oracle GraalVM 配置相比,此优化提供了约 6% 的运行时加速。通过使用 ML 配置文件推理构建原生可执行文件,您可以预期二进制文件大小会略微增加 1%-2%。此优化在 Oracle GraalVM 中默认启用(GraalVM 社区版中不可用)。要禁用它,请使用以下选项:-H:-MLProfileInference
  • Native Image SBOM 现在包含一个用于运行时组件的单个 SBOM 组件。此组件使用可执行文件的 java.vm.version 属性来识别版本,并属于新的 graalvm-native-image 产品。

构建输出改进

  • 构建器现在可以生成构建报告,帮助您更好地理解可执行文件的内容。使用 -H:+BuildReport 来尝试这个新的实验性功能。
  • 改进了内部错误报告,使其更加用户友好。清晰的消息会告诉用户如何操作:检查错误报告,如果无法解决问题,请附带错误报告提交问题。受 HotSpot 启发,错误报告的默认文件名为 ./svm_err_b_<timestamp>_pid<pid>.md。这还添加了一个新选项 -H:ErrorFile,允许您选择不同的错误报告文件名。参见 #5414
  • 调整了 native-image 的构建输出,以报告类型(原始类型、类、接口和数组)而不是类,并修订了 -H:BuildOutputJSONFile 的输出架构。
  • native-image --version 命令的输出和各种 Java 属性(例如 java.vm.version)与 OpenJDK 对齐。要区分 GraalVM 社区版、Oracle GraalVM 和其他供应商的 GraalVM 分发版,请参考 java.vm.vendor

调试和监控体验改进

  • 不带参数使用 --enable-monitoring 选项已弃用。该选项不再默认为 all。相反,请始终明确指定要启用的监控功能列表,例如 --enable-monitoring=heapdump,jfr,jvmstat
  • 添加了 -XX:HeapDumpPath 选项以控制堆转储的创建位置。
  • 为应用程序监控添加了更多 JFR 事件:ExecutionSampleObjectAllocationInNewTLABJavaMonitorInflate
  • 改进了 Windows 上的调试:调试信息现在包含有关 Java 类型的信息。(与 Red Hat 合作。)
  • 在 Native Image 中添加了对 JMX 的实验性支持。例如,使用 --enable-monitoring=jmxclient,jmxserver 可在可执行文件中同时包含 JMX 客户端和服务器。更多信息请阅读此处。(与 Red Hat 合作。)
  • 为 Native Image 启用了 JFR 事件流。此功能是实验性的。(与 Red Hat 合作。)

Native Image 更新日志中查找更多更新。

JavaScript 和 Node.js

  • 将 Node.js 更新到 18.14.1 版本。
  • 增加了 BigInteger 互操作性支持。请注意,外部 BigIntegers 需要使用 BigInt 函数进行显式类型转换,才能选择 JS BigInt 语义。默认语义是将所有外部数字视为 JavaScript Number 值,无论原始值或类型如何。算术运算符执行隐式有损转换为双精度浮点数。比较运算符在可能的情况下尝试进行精确的值比较。JavaScript BigInt 值现在可以转换为 java.math.BigInteger 主机对象,尽管如果目标类型不明确或不存在,可能仍然需要目标类型映射以确保一致的类型映射。
  • 在 GraalVM JavaScript 运行时中实现了几个新的 ECMAScript 提案

项目更新日志中查找更多更新。

多语言嵌入

  • 这是第一个支持在代码沙盒中运行不可信应用程序的版本。沙盒策略 Context.Builder#sandbox(SandboxPolicy) 具有四种不同的沙盒级别:ISOLATEDUNTRUSTEDTRUSTEDCONSTRAINED,旨在让用户在主机应用程序和访客代码之间建立安全边界。策略通过将其传递给 Engine.Builder#sandbox(SandboxPolicy)Context.Builder#sandbox(SandboxPolicy) 构建器方法来设置。主机代码可以使用,例如,UNTRUSTED 策略执行不可信的访客代码。主机代码还可以执行多个互不信任的访客代码实例,这些实例将相互保护。在多语言沙盒指南中了解更多信息。代码沙盒目前仅支持 Javascript。SandboxPolicy.ISOLATEDSandboxPolicy.UNTRUSTED 策略在 GraalVM 社区版中不可用。
  • 与代码沙盒实现相关,新增了 TraceLimits 选项,用于测量访客应用程序的资源消耗并获取实际的沙盒参数。
  • 新增了 IOAccess API:一个多语言上下文的 IO 访问配置。IO 访问配置决定了访客语言如何访问主机 IO。新的 IOAccess 类提供了一个预定义的配置,用于禁用主机 IO 访问,或启用完整的主机 IO 访问。可以使用 IOAccess 构建器创建自定义配置。
  • java.lang.BigInteger 添加到 Polyglot Value API。默认情况下,所有类型为 java.lang.BigInteger 的主机值现在都被解释为数字值 (Value.isNumber()),这与之前不同。为了恢复旧行为,将 HostAccess.Builder.allowBigIntegerNumberAccess(boolean) 设置为 false。请注意,对于无法容纳在长整型值中的数字,语言支持可能会有所不同。某些语言(如 JavaScript)可能需要对主机大整数进行显式转换。其他语言(如 Ruby 或 Python)可以在没有显式转换的情况下使用大整数。这同样适用于跨访客语言传递的值。请参阅 #2737
  • 添加了语言资源自动复制功能,用于在 Native Image 中嵌入 Truffle 语言。文档可在此处查阅。

完整的更改列表可在更新日志中查看。

Truffle 语言和工具实现

  • 为 Truffle DSL 实现了几项新功能,以提高性能。特别是引入了一个名为 @GenerateInline 的新注解,它允许 Truffle 节点自动进行对象内联。对象内联的 Truffle 节点成为单例,从而减少内存占用。这与 @GenerateCached@GenerateUncached 类似,后者生成缓存或未缓存的节点版本。有关详细信息,请参阅文档

其他有助于性能改进的更新包括

  • 更新后的 Truffle DSL 节点在专门化过程中不再需要节点锁,从而提高了首次执行性能。现在使用 CAS 风格的内联缓存更新来避免在守卫中调用 CallTarget.call(...) 时发生死锁。内联缓存继续保证没有重复值,并且不受竞态条件影响。语言实现应注意,减少争用可能会暴露出语言中其他线程安全问题。
  • 通过合并状态生成的字段、排除位集以及改进专门化数据类生成以考虑激活概率,从而改进了 Truffle DSL 节点的内存占用。为了获得最佳结果,专门化应按激活概率排序。
  • 通过自动将枚举类型的缓存参数值内联到状态位集中,改善了内存占用。
  • Truffle DSL 现在会发出更多建议警告。例如,它会发出关于内联机会、缓存共享或何时应将缓存初始化器指定为 @NeverDefault 的警告。为了简化迁移工作,添加了新的方法来暂时为 Java 包抑制这些警告。有关可能的警告列表和进一步的使用说明,请参阅文档
  • 未关闭的多语言引擎在虚拟机关闭时不再自动关闭。它们随虚拟机一起消亡。因此,在虚拟机关闭事件中,未关闭引擎上的活动工具不会调用 TruffleInstrument#onDispose。如果工具在处理前需要执行某些特定操作,例如打印某种摘要,则应在 TruffleInstrument#onFinalize 中完成。
  • 实现了控制代码沙盒限制的策略。默认情况下,语言和工具只支持 TRUSTED 沙盒策略。
    • 如果一种语言希望支持更严格的沙盒策略,它必须:
      • 使用 TruffleLanguage.Registration#sandbox() 指定其满足的最严格的沙盒策略。
      • 对于每个选项,语言必须通过 Option#sandbox() 指定该选项可用的最严格的沙盒策略。默认情况下,选项具有 TRUSTED 沙盒策略。
      • 如果语言需要额外的验证,可以使用 TruffleLanguage.Env#getSandboxPolicy() 获取当前的上下文沙盒策略。
    • 如果一个工具想要针对更严格的沙盒策略,它必须:
      • 使用 TruffleInstrument.Registration#sandbox() 指定其满足的最严格的沙盒策略。
      • 对于每个选项,工具必须通过 Option#sandbox() 指定该选项可用的最严格的沙盒策略。默认情况下,选项具有 TRUSTED 沙盒策略。
      • 如果一个工具需要额外的验证,它可以使用 TruffleInstrument.Env#getSandboxPolicy() 来获取引擎的沙盒策略。

Truffle 更新日志中查找更多更新。

Truffle 上的 Java (Espresso)

新功能

改进

  • 启用了通过互操作调用重载和可变参数方法。
  • 改进了与外部异常的互操作性。现在可以提供堆栈跟踪,并且可以使用类型映射来显式映射异常。

Python

性能改进

  • 添加了 Python C API 接口的新实现,默认情况下使用完全原生的执行。这提高了性能和与某些在原生代码中花费大量时间的扩展(如 SciPy、PyTorch 等)的兼容性,但可能对频繁跨越 Python/原生边界的工作负载产生负面影响。有新的选项来控制扩展的构建和运行方式:python.NativeModulespython.UseSystemToolchain。新的默认行为是使用主机系统的工具链而不是 GraalVM 附带的 LLVM 工具链来构建扩展,并原生运行所有模块。一个新的启动器 (graalpy-lt) 可用于获取旧行为,这对于调试可能很有用。
  • 我们网站上报告的性能数据现在基于社区 pyperformance 基准测试套件的结果,衡量 GraalPy 相对于 CPython 和 Jython 的几何平均加速。这使得比较和重现我们的结果变得更加容易。

平台更新

  • 实现了在 Windows 上构建和运行基本的 GraalPy 工作负载。这使得 Windows 用户可以构建和使用 GraalPy,特别是在嵌入到 Java 中时。
  • 将适用于 Virtualenv 的 GraalPy 插件作为内置模块添加,以便在 GraalPy 上使用 virtualenv 创建虚拟环境开箱即用。
  • 更新了内置的 venv 模块,以使用符号链接而不是委托给基础 GraalPy 的生成的 shell 脚本来创建虚拟环境。

兼容性改进

  • 将语言版本和标准库更新至 3.10.8,使其与更多近期模块和包兼容。
  • 更新了 GraalPy 的分发布局以匹配 CPython。这减少了各种构建系统发现 GraalPy 库位置所需的补丁数量。
  • 更新了 numpypandas 版本。
  • 使用 ginstall 实现了 scipyscikit_learn

完整的更新列表可在项目更新日志中找到。

Ruby

新功能

  • 已更新到 Ruby 3.1.3。
  • 现在支持外部大整数,并可与所有 Numeric 运算符一起使用。

性能

  • 使 psych 使用系统 libyaml,这改进了解析 YAML 时的预热时间。这意味着 libyaml 现在是一个依赖项。请参阅如何安装 LibYAML
  • 现在在 C 调用退出时完成封装在对象中的原生结构的标记,以减少内存开销。
  • 通过实现 cloneUninitialized(),优化了调用目标的拆分(复制)。
  • Process.pid 现在像 $$ 一样按进程缓存。
  • 修复了对于在给定调用点通过多次调用而不断增长的 Array 方法的重复去优化问题。

错误修复

  • 修复了 macOS 上的 spawn(..., fd => fd) 问题,由于 macOS 的一个 bug,它无法工作。
  • 修复了 rb_gc_register_address()/rb_global_variable() 以读取最新值(参见 #2721, #2734)。

完整的更改列表可在项目更新日志中找到。

LLVM

  • 将 LLVM 工具链更新到 15.0.6 版本。
  • musl libc 更新到 1.2.3 版本。
  • 在 Linux AArch64 架构上实现了 long double (128 位浮点数)。

WebAssembly

  • 添加了 DWARFv4 的实验性调试支持。这使得 C、C++ 和 Rust 应用程序的调试成为可能。
  • 添加了对 Memory64 的实验性支持。该功能可以通过选项 --wasm.Memory64=true 启用。
  • 实现了 Bulk-MemoryReference-Types 提案。它们可以通过选项 --wasm.BulkMemoryAndRefTypes 禁用。

联系我们