22.1.0

(2022-04-26)

平台更新

  • 新增了对 Apple Silicon 的支持,这是一款由 Apple Inc. 生产的基于 ARM 的片上系统。您可以从 GitHub 下载此平台的 GraalVM Community 发行版。请查找 darwin-aarch64。目前,您可以通过此发行版使用 libgraal 的 JVM、Native Image、JavaScript 运行时以及 Truffle 上的 Java 功能。此支持仍处于实验阶段。

  • 更新了 GraalVM Community Edition 构建所基于的 OpenJDK 版本,包括:

Java 和编译器更新

  • 计数循环是编译器用于确保循环迭代限制是绑定整数的一种抽象。此类循环受制于主要的优化,例如向量化和部分展开。Truffle API 提供了分析和推测循环计数器值具有最大值的能力,该最大值可以被编译器视为常量。Graal 编译器现在遵循这种推测,并且如果最大值足够小,将展开此类循环。例如,以下 Ruby 循环现在将被展开
      [1, 2].each { |e| print e }
    
  • 实现了 JDK 17 中所有由 @IntrinsicCandidate 注解的内部函数。
  • 移除了 DuplicateIrreducibleLoops 选项。要禁用不可约循环处理,请将 -Dgraal.MaxDuplicationFactor 设置为小于或等于 1 的值。对于预先编译 (AOT) 的情况,为处理不可约循环所付出的努力得到提升,以使 Native Image 支持更多具有不可约循环的程序。特别是,这缓解了 此问题

Native Image

  • 选项 --allow-incomplete-classpath 现在默认启用并已弃用,因为它不再需要。这意味着,默认情况下,链接错误现在在可执行文件运行时而不是构建时抛出。新选项 --link-at-build-time 允许在构建时为指定的包和类列表进行链接。您可以在命令行上提供任意数量的带有特定参数的 --link-at-build-time 选项,例如,native-image --link-at-build-time=foo.bar,foobar.core.MyClass --link-at-build-time=my.other.RandomClass ...。请参阅 #4305
  • 新增了“快速构建”模式,以减少开发过程中生成原生可执行文件所需的时间。使用现有选项 -Ob 选择优化级别启用它,其中 b 表示“针对构建时间优化”。请注意,此模式可能会对峰值性能和生成的可执行文件大小产生负面影响,因此仅建议用于开发目的。
  • 新增了实验模式,用于使用 跟踪代理 生成条件配置。该代理现在可以使用一种在调用图上操作的启发式方法生成条件反射配置,即,只有当谓词类可达时才注册的反射元素。支持两种模式:
    • 通过将 experimental-conditional-config-filter-file=<path> 传递给代理。在此模式下,代理直接生成配置。过滤器告诉代理哪些代码属于用户的应用程序。条件仅在属于用户应用程序的类上生成。
    • 通过将 experimental-conditional-config-part 传递给代理,并使用 native-image-configure generate-conditional --user-code-filter=<path> --input-dir=<agent-ouput> --output-dir=<config-output> 生成配置。有关更多信息,请查看 Native Image 文档
  • 引入了代码大小改进,有助于减少原生可执行文件的大小。native-image 生成器的性能改进和内存占用减少,导致构建时间更快(独立于新的“快速构建”模式)。下表显示了构建 Spring petclinic-jdbc(一个知名的大型应用程序)的可执行文件所需的文件大小和时间。这些数字是在一台运行 Linux、AMD64、JDK 11、GraalVM Enterprise、spring-native 0.10.3 的开发机器上测量的。

    GraalVM 版本 构建时间 可执行文件大小 使用 -Ob 构建时间
    GraalVM 21.1 2 分 50 秒 138 MB  
    GraalVM 21.2 2 分 43 秒 133 MB  
    GraalVM 21.3 2 分 13 秒 121 MB  
    GraalVM 22.0 2 分 20 秒 119 MB  
    GraalVM 22.1 2 分 5 秒 103 MB 1 分 17 秒
  • 新增了对 Apple Silicon(基于 ARM 的片上系统)的支持。其中一个缺失的功能是,例如,对 Truffle 即时编译的支持。
  • 改进了 Record 类的提前编译。例如,Record 类的注解现在可以在可执行文件运行时访问。
  • 新增了对以下 JFR 事件的支持:SafepointBeginSafepointEndGarbageCollectionGCPhasePauseGCPhasePauseLevel(均由 Red Hat 贡献)。所有与 GC 相关的 JFR 事件目前仅限于 串行 GC
  • JFR 现在可用于分析 native-image 工具本身,例如,通过在 native-image 命令行中添加 -J-XX:StartFlightRecording=dumponexit=true
  • 改进了 static synchronized 方法的处理:锁不再存储在辅助监视器映射中,而是存储在可变的 DynamicHubCompanion 对象中。通过此更改,static 方法的同步与实例方法的同步一样快。
  • 新增了对 AccessControlContext 的支持,它有助于控制可以使用特权操作修改的上下文。
  • 引用处理现在默认在单独的线程中执行。这有助于防止在同一线程中处理引用和运行垃圾回收时偶尔发生的死锁。
  • 新增了在原生可执行文件中包含辅助方法的可能性,这些方法可以从 gdb 调用,从而有助于调试原生可执行文件。将选项 -H:+IncludeDebugHelperMethods 提供给 native-image 以启用此功能。
  • 弃用了 JDK8OrEarlierJDK11OrLater 类,因为 JDK 8 不再受支持。它们将在未来的版本中移除。
  • 每个带注解的元素(类、方法、字段等)都将包含在镜像中,无论其可达性如何。这可能需要一些配置更改,特别是对于动态生成的代理。例如,使用以下代码
      @AccessedAnnotation
      @NonAccessedAnnotation
      class Example {
      boolean func(Object obj) {
          Proxy.getProxyClass(classLoader, Example.class.getDeclaredAnnotations());
          obj.isAnnotationPresent(AccessedAnnotation.class);
          }
      }
    

    以前,您只需指定 [AccessedAnnotation] 配置。现在代理配置将看起来像 [AccessedAnnotation], [NonAccessedAnnotation]

  • 防止了 META-INF/MANIFEST.MF 中的类路径条目以错误顺序处理。请参阅 #4374
  • 现在,即使 native-image 构建器在模块路径上运行(使用 --module-path 标志构建时),使用 -H:CompilerBackend=llvm 也有效。请参阅 #4336
  • 改进了在容器内构建原生可执行文件,如果资源路径包含正斜杠 / 作为工作目录。请参阅 #4002

JavaScript

  • Node.js 已更新至版本 16.14.2。
  • 实施了多项提案
    • Intl.NumberFormat v3 提案。
    • Array Grouping 提案。它在使用 --js.ecmascript-version=staging 选项的 ECMAScript 阶段模式下可用。
    • Temporal 提案。它通过实验选项 --js.temporal 提供。
    • Array Find from Last 提案。它在使用 --js.ecmascript-version=staging 选项的 ECMAScript 阶段模式下可用。
  • 新增了选项 --js.string-lazy-substrings,默认为 true,用于切换 String 切片的复制行为。启用时,String 切片在内部创建 String 视图而不是复制给定的 String 区域,这会提高性能但也可能增加内存利用率。

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

Ruby

  • 实现了完整的 Ruby 3 关键字参数语义(请参阅 #2453)。
  • 外部异常现已完全集成,拥有 Exception 的大多数方法,并且可以使用 rescue Polyglot::ForeignExceptionrescue foreign_meta_object 进行捕获(请参阅 #2544)。
  • 外部异常不再被转换为 RuntimeError,而是保持为外部异常,请参阅 文档 了解如何捕获它们。
  • 为 digest 默认 gem、RubyGems 和 Bundler 添加了各种修复(#2577#2605#2586)。
  • 修复了 Module#const_get 在嵌套模块不存在时会引发 NameError 的问题,这是 Rails 7 scaffolding 所需的。
  • 移除了解释器中方法调用时额外的数组分配,以提高预热性能。
  • 减少了 C 扩展的内存占用(Init_ 分配与其余部分分离,更少句柄等)。
  • 优化了 Dir[]String#<=>Regexp#match?File.read(请参阅 #2536)。

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

Python

  • 新增了模块冻结支持,使 Python REPL 启动速度快 30%,内存使用量减少 40%。
  • ssl 模块中新增了对更多私钥格式(PKCS#1,密码保护)的支持。
  • 改进了与以下 PyPI 包的兼容性:lxmlpytzPillowurllib3setuptoolspytesttwinejinja2six

完整的更改列表在 GitHub 上的 更新日志 中。

R

  • JavaGD 现在是默认的图形子系统。--R.UseInternalGridGraphics 选项已弃用。graphicsgridgrDevices 基本包中的大多数函数都受支持。支持的设备有 SVG、PNG、JPEG、BMP、AWT。显示列表已完全实现。有关更多信息,请参阅文档
  • GraalVM 的 R 运行时现在使用系统 zlib 而不是其自身的库副本。这使得 zlib 成为 GraalVM 的 R 运行时的必需组件,然而,大多数 Linux 发行版和所有受支持的 macOS 版本都预装了 zlib。可能不是这种情况的唯一可想象的情况是一些优化过的精简 Docker 镜像。

项目 更新日志 可在 GitHub 上查阅。

LLVM 运行时

  • 新增了对 C/C++ 线程局部存储的支持。
  • 新增了对新互操作 API 的支持
  • --llvm.* 命名空间中的自定义日志选项(例如 --llvm.traceIR)替换为 Truffle Logger 选项(--log.llvm.*,例如 --log.llvm.TraceIR.level=FINER)。

请参阅 GitHub 上项目 更新日志 中的完整更改列表和选项替换。

Truffle 上的 Java

  • 在单线程模式下启用了显式引用处理。这意味着单线程模式可在更多情况下使用,以防止资源泄漏。它作为名为 <ProcessReferences> 的命令提供,可以通过 context.eval("java", "<ProcessReferences>") 运行。
  • 引入了新的热插拔功能
    • 新增了对更改超类和已实现接口的支持。
    • 新增了对“在层次结构中移动字段”重构的支持,其中状态得以保留。
    • 默认开启了更改字段和类访问修饰符。
  • 在许多情况下(包括使用监视器时),能够更及时地响应 Truffle 安全点
  • 采用了 AbstractTruffleException API,以改进在执行客户语言程序期间抛出的异常处理。
  • 新增了用于读取 jimageslibs/modules)的实现,该实现默认启用。这在使用 LLVM 后端时缩短了上下文启动时间。使用 --java.JImage=native 可恢复旧的实现。
  • Truffle LLVM Java 库上的 Java 现在支持 macOS(以前仅适用于 Linux 发行版),并且可以使用 GraalVM Updater 安装:gu install espresso-llvm

多语言嵌入

  • 对于同时具有数组元素和 Map 成员的值,默认的 对象目标类型映射 (Value.as(Object.class)) 已从 Map 更改为 List。请注意,这是一个不兼容的更改。依赖于在强制转换为 Object 目标类型后仍为动态类型 Map 的嵌入者将必须迁移其代码。以前的行为可以通过自定义 目标类型映射 恢复,例如
      HostAccess access = HostAccess.newBuilder(HostAccess.EXPLICIT)
              .targetTypeMapping(Value.class, Object.class, v -> v.hasMembers() && v.hasArrayElements(), v -> v.as(Map.class))
              .build();
      try (Context c = Context.newBuilder().hostAccess(access).build()) {
          // run application
      }
    

更新日志 可在 GitHub 上查阅。

Truffle 语言和工具实现

  • 为 Truffle 语言添加了 API,即 Language#getWebsite(),并为工具添加了 Instrument#getWebsite(),以便为网站提供信息。开发人员可以指定一个 URL,其中包含有关其语言/工具的更多信息。
  • 新增了 TruffleStrings 实现,这是一种可以在 Truffle 语言(使用 Truffle 框架实现的语言)之间共享的基本 String 类型。有关更多信息,请查阅 Truffle Strings 指南
  • 新增了 @GeneratePackagePrivate 注解,即使模板节点是 public 的,也可以将生成节点的可见性更改为 *包私有*。
  • 新增了 TruffleLanguage.Env#createHostAdapter,它接受主机符号和主机类作为要扩展的类型,取代并弃用了基于 java.lang.Class 的版本。
  • Option 添加了 usageSyntax 属性,使开发人员能够指定其选项期望的语法。有关更多信息,请参阅 Javadoc
  • 移除了已弃用的 TruffleException(自 GraalVM 20.3.0 起已弃用)。AbstractTruffleException 不再实现 TruffleException。从 TruffleException 继承的 AbstractTruffleException 方法已被移除。作为此次移除的一部分,有关语言 如何处理异常 的建议已更新。
  • TruffleContext.Builder 添加了方法,允许在新建的上下文被取消、硬退出或关闭时抛出自定义的客户异常,并且相应的异常即将到达外部上下文。如果未使用自定义并且新上下文被取消、硬退出或关闭,Truffle 将新抛出一个内部错误。
  • 弃用了 TruffleRuntime.getCurrentFrame()TruffleRuntime.getCallerFrame()。它们鼓励不安全地使用 FrameInstance 类。

本版本中其他弃用和更新已列在 项目更新日志 中。

工具

适用于 Java 的 GraalVM VS Code 扩展

  • 更新了工作流,以使用 VS Code 中内置的 GraalVM 安装向导下载和安装 GraalVM Enterprise Edition 及其附带组件。与以前一样,要安装 GraalVM Enterprise 核心或附加组件,用户必须提供有效的电子邮件地址并接受许可协议。安装向导现在将使用一个与用户电子邮件地址绑定的 **下载令牌**,并定义一套已接受的许可证。电子邮件验证和许可证接受将通过用户的电子邮件客户端进行。

  • 新增了 **原生镜像** 面板,以自动化跟踪和注册动态特性调用的过程,从而在 VS Code 中构建原生可执行文件变得更加容易。当您安装 GraalVM 和 Native Image 后,此面板将可用

    VS Code: Add Native Image Agent Panel

  • 改进了 VisualVM 与扩展的 VS Code 集成。现在,您无需创建特殊的启动配置即可打开 VisualVM 并开始监视 Java 进程。单击 **VISUALVM** 面板中的播放按钮

    VisualVM and VS Code Integration

  • 改进了 Groovy 支持,包括 **运行和调试** Groovy 的能力。

GraalVM 更新器

  • 增强了通过命令行使用 GraalVM Updater (gu) 将组件安装到 GraalVM Enterprise Edition 的工作流程。GraalVM Updater 将创建并使用一个 **下载令牌**,该令牌绑定到用户的电子邮件地址,并定义一组已接受的许可证。与以前一样,要安装组件,用户必须提供有效的电子邮件地址并接受许可协议,但现在电子邮件验证和许可接受将通过用户的电子邮件客户端进行。有关更多信息,请参阅文档

联系我们