21.1.0

(2021-04-20)

Java 更新

GraalVM 社区版所基于的 OpenJDK 版本已更新至

  • 8u292(适用于基于 Java 8 的 GraalVM 社区版)
  • 11.0.11(适用于基于 Java 11 的 GraalVM 社区版)
  • 16.0.1(适用于基于 Java 16 的 GraalVM 社区版)

GraalVM 企业版所基于的 Oracle JDK 版本已更新至

平台更新

  • Java 16(实验性)支持:基于 Oracle Java 16 和 OpenJDK 16 的 GraalVM 分发版现已可供下载。
  • macOS 平台支持:基于 OpenJDK 8 的 GraalVM 社区版 macOS 构建不再生成。基于 Oracle JDK 8 的 GraalVM 企业版 macOS 构建仍可用。
  • Linux AArch64 平台兼容性:此版本中适用于 Linux AArch64 架构的 GraalVM 分发版仍处于实验阶段。支持的功能包括 GraalVM 编译器、gu 工具、Node.js JavaScript 运行时、Native Image 和一些开发工具。
  • Windows 平台兼容性:要在 Windows 平台上运行基于 OpenJDK 8u292 的 GraalVM 社区版,需要安装 MSVCR100.dll 可再发行软件包(更多详细信息,请参阅问题 #3187)。

编译器

  • 增加了对将反向(尾部计数)循环检测为计数循环的支持。GraalVM 企业版现在将此类循环检测为计数循环,使其能够像所有其他计数循环一样进行分析和优化。这些循环受完全展开、部分展开、防护优化和向量化的约束。此新功能可以使用 -Dgraal.DetectInvertedLoopsAsCounted=false 禁用。(仅在 GraalVM 企业版中可用。)
  • 在 GraalVM 企业版中新增了一种新颖的循环反转优化。这增加了编译器支持,可从常规循环生成反向循环。与常规的头部计数循环相比,反向循环在指令级并行和优化能力方面具有卓越的特性。对于测试反向循环形状的微基准测试,我们看到了高达 30% 的性能改进。循环反转默认开启,并可以通过 -Dgraal.LoopInversion=false 禁用。(仅在 GraalVM 企业版中可用。)
  • 添加了一项新的优化,可分析由 x == y 形式的条件保护的代码,如果替换能够带来进一步优化的潜力,则将 x 的所有用法替换为 y (反之亦然)。(仅在 GraalVM 企业版中可用。)
  • 增强了 SIMD 向量化功能,以支持向量字节反转(例如,Integer.reverseBytes)。SIMD 向量化仍处于实验阶段,默认未启用。可以使用 -Dgraal.VectorizeSIMD=true 启用。(仅在 GraalVM 企业版中可用。)
  • 添加了对使用 hash = c * hash + array[i] 对类 hashCode 循环进行向量化的支持。可以通过 -Dgraal.VectorizeHashes=false 禁用。(仅在 GraalVM 企业版中可用。)
  • 消除了加载数组元素到 Node 的强制类型转换,以防止在易失性字段从数组加载时,丢失元素类型信息,并导致不必要的类型转换的情况。ConcurrentHashMap 中的此方法可以作为一个示例: 
    static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
          return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
      }
    
  • 消除了 x86 上顺序易失性写入时不需要的内存屏障。在 ConcurrentHashMap 等类中存在模式,其中(内联后)可以按顺序进行大量易失性写入。GraalVM 编译器现在省略了序列中除最后一次写入之外的所有写入的内存屏障,从而加快了 ConcurrentHashMap.transfer 等方法的速度。

Native Image

  • 改进了对本地化的支持。现在可以指定应包含在原生可执行文件中的区域设置,以及应为默认值的区域设置。例如,要将默认区域设置切换为德语并同时包含法语和英语,请使用 -H:DefaultLocale=de -H:IncludeLocales=fr,en。所有区域设置都可以通过 -H:+IncludeAllLocales 包含。
  • 已弃用 --enable-all-security-services 选项,因为它不再必要。现在,安全服务在通过静态分析发现使用时会自动注册。
  • 改进了对 Windows 的支持:应用程序现在对参数执行文件 globbing(文件模式匹配)。
  • 增加了对原生镜像构建的报告,以生成多个工件。构建结果会写入到 imagename.build_artifacts.txt 文件中。
  • 修复了 Linux 和 macOS 上的一个错误,该错误导致在传递 -g 以生成调试信息时,所有方法的本地符号都包含在原生镜像中。方法符号对于调试来说不是必需的,因为 Dwarf 调试信息也包含此信息。当需要本地符号时,例如用于某些分析器时,可以使用 -H:-DeleteLocalSymbols 将它们包含在镜像中(独立于 -g 选项)。
  • 允许在同一个进程中存在多个不同的原生镜像,例如一个应用程序和一个共享库。这是 Linux 平台所必需的。
  • 自动标记更多类以进行构建时初始化。这减少了运行时类初始化的开销。

多语言运行时

  • 默认启用多层编译。此功能最初在 20.3 版本中作为实验性选项引入。Truffle 现在使用两个编译层。第一层优化编译速度,并重用 GraalVM 编译器经济配置,仅对简单方法进行方法内联以执行快速编译。第二层在第一层编译完成后,启用所有 GraalVM 编译器的优化进行编译。我们的基准测试结果表明,这显著改善了大多数语言的预热时间。
  • 为需要可选依赖于最新 JVMCI 版本 21.1-b02 的语言实现添加了新功能(问题 JDK-8263776)。在下一个版本 21.2 中,我们计划将其中一些功能用于核心运行时功能,因此 JVMCI 21.1-b02 将成为必需的依赖项。这将导致不支持 JVMCI 21.1-b02 的 JDK 版本无法进行运行时编译。请注意,所有 Truffle 语言仍可在任何 JDK 上执行,但不支持运行时编译。 
  • 引入了新的实验性标志来设置多层编译的编译阈值:--engine.FirstTierCompilationThreshold 设置第一层的阈值,--engine.LastTierCompilationThreshold 设置第二层的阈值。如果禁用多层编译,可以使用 --engine.SingleTierCompilationThreshold=x。原始选项 --engine.CompilationThreshold 现已弃用,并将在未来版本中移除。
  • 添加了一个受 HotSpot 启发的新的实验性编译队列实现。此实现默认尚未启用,但可以使用 --engine.TraversingCompilationQueue 选项进行尝试。此标志预计将减少预热时间。计划在下一个版本中进行更多更改和增强,届时它有望成为默认实现。
  • 弃用了 --engine.CompilationThreshold 选项。请改用 --engine.FirstTierCompilationThreshold 和 --engine.LastTierCompilationThreshold

Truffle 上的 Java

  • 对 Java 调试线协议 (JDWP) 支持引入了许多修复和改进。修复了许多边缘情况,这在启用调试时显著提高了 Truffle 上 Java 的性能(最高可达 200 倍!)。
  • 提供了方法重新定义的修复:反射访问和 MethodHandles 现在遵循方法更改。
  • 添加了对信号处理程序(sun.misc.Signal / jdk.internal.misc.Signal)的支持。这意味着现在在使用 Ctrl-C 关闭程序时会运行关闭挂钩。
  • 移除了对已弃用 Scope API 的依赖,转而实现了新引入的 NodeLibrary
  • 修复了 GraalVM 嵌入器 API (PolyglotException) 报告的客户机堆栈跟踪。
  • 改进了对限制线程创建的支持。

JavaScript

  • Node.js 更新到版本 14.16.1。
  • Node.js 支持默认未启用,如果需要,必须使用 GraalVM Updater 明确安装:gu install nodejs。JavaScript 运行时仍包含在 GraalVM 基础安装中。
  • 添加了迭代器互操作性支持。它允许通过 Value API(hasIterator()getIterator()hasIteratorNextElement()getIteratorNextElement())使用 JavaScript 迭代器,以及在 GraalVM 的 JavaScript 运行时中迭代来自其他语言的可迭代对象(例如,通过 for-of 循环),反之亦然。
  • 启用了缓冲区互操作性支持。它允许主机 ByteBuffers 和来自其他语言的缓冲区与 JavaScript 类型化数组(例如,new Uint8Array(foreignBuffer))和 DataView 一起使用,无需复制。它还支持通过 Value API(readBuffer*writeBuffer*)访问 ArrayBuffers
  • 实现了 WebAssembly JavaScript 接口的实验版本,该版本允许从 JavaScript 程序中调用 WebAssembly 程序(可通过 --js.webassembly 选项启用)。

此项目的变更日志可在项目仓库中找到。

LLVM 运行时 (Sulong)

  • 完全移除了使用“原生模式”构建 GraalVM 或原生镜像的能力(因此仅 --llvm.managed 模式有效)。(仅在 GraalVM 企业版中可用。)
  • 使指向外部“类缓冲区”对象(例如 JS ArrayBuffer)的指针能够像原生缓冲区一样透明地访问。
  • 除了 Polyglot API 之外,还增加了对使用常规 dlopen 加载位码模块的支持。 
  • 增加了对 Linux AArch64 平台的实验性支持。
  • 实施了一项健全性检查,以验证加载的位码文件是否针对 GraalVM LLVM 运行时正确编译。特别是,当加载为托管模式构建但在原生模式中使用(反之亦然)的位码时,此检查将失败。此检查可以通过 --llvm.verifyBitcode=false 选项转换为非致命警告。

项目变更日志可在 GitHub 上获取。

Ruby

  • 实现了对 Ruby 2.7 更完整的支持(更多详细信息请参阅 #2004)。
  • 多层编译现在默认启用,显著改善了预热时间。
  • 链接到静态库的 C 扩展现在通常通过在安装 gems 时将 GraalVM LLVM 工具链添加到 PATH 来工作。
  • 改进了递归检查的性能(#2189)。
  • 通过避免同步改进了随机数生成性能(#2190)。
  • 默认情况下实现了每个块创建一个调用目标的能力,而不是两个。
  • 优化了类变量的一些使用(#2259)。
  • 通过使几个需要调用者帧的方法始终内联在其调用者中,加快了解释器速度并减少了占用空间。
  • 添加了通过语言绑定访问交互式 Binding 的局部变量的支持:context.getBindings("ruby").putMember("my_var", 42);。请参阅 #2030
  • 使信号处理程序在不触发多线程的情况下运行。
  • 实现了 Debug Inspector C API。
  • 切换到 io-console C 扩展,以在 irb 中获得更好的性能和兼容性。
  • 更新到 irb 1.3.3 和 reline 0.2.3,这使得在 IRB 中粘贴代码的速度合理加快(#2233)。
  • TruffleRuby 的独立构建现在基于 JDK11(以前使用 JDK8)。

更多详细信息可在 TruffleRuby 变更日志中获取。

Python

  • 改进了对 Java 子类化的支持,并提供了新的互操作性 API 以改善 Jython 迁移路径。以前在 Jython 中经常请求和可用的功能,例如从 Java 方便地迭代 Python 类型、从 Python 实现 Java 抽象类和接口、在 Python 代码中捕获和重新抛出 Java 异常,现在 GraalVM 的 Python 运行时也提供了这些功能,从而使迁移更容易。
  • 增加了 SSL 支持。这允许开箱即用地安装 Python 包。现在用户可以运行 Python pip 安装程序来下载 Python 包及其依赖项,就像在 CPython 上一样。
  • posix API 添加了一个完全原生后端。这为文件系统访问提供了更好的性能和更强的兼容性。
  • 增加了对带 GIL 的多线程支持。GraalVM 的 Python 运行时中的多线程支持与 CPython 的程度相同。也就是说,对于大多数工作负载,只有并发性,没有并行性。
  • 增加了对当前 HPy Python C API 的支持,以更好地运行 C 扩展。这是一个正在进行的研究项目,与 PyPy 项目的成员和开普敦大学合作,旨在为 NumPy 和其他流行的 Python C 扩展提供更快的 API。

更多详细信息可在项目变更日志中获取。

R

  • 将 GraalVM 的 R 运行时升级到 R 4.0.3
    • 使 GraalVM R 运行时与 R 4.0.3 大部分兼容;
    • 迁移到基础包和推荐包的新版本;
    • 实现了 R 4.0.3 的一些新功能(完整列表请参阅变更日志)。
  • 将 install.packages 默认使用的 CRAN 快照升级到 2021-02-01
    • GraalVM R 运行时上一些最流行包的新版本支持正在进行中;
    • 已知问题包仍然存在:dplyr 1.0.3、ggplot 3.3.3、knitr 1.31。

更多详细信息可在项目变更日志中获取。

WebAssembly (GraalWasm)

  • 将 GraalWasm 解释器的加速和整体峰值性能显著提高了 10 倍以上。
  • 提供了基本的 WASI 函数,允许通过 Truffle 文件系统层操作文件和访问文件系统。
  • GraalWasm 现在通过了官方 WebAssembly 测试套件中的大部分测试。
  • 提高了独立 GraalWasm 启动器的速度,并提升了整体峰值性能。
  • 实现了 WebAssembly-JavaScript 接口规范,该规范允许从运行在 GraalVM JavaScript 运行时上的 JavaScript 程序中调用 WebAssembly 程序。
  • 实现了对 .wasm 文件中自定义名称部分的解析,以使堆栈跟踪更用户友好。
  • 使 GraalWasm 解释器遵循二进制验证规则。
  • 在解析和链接二进制文件时,引入了对内存/表/函数计数限制的检查,如规范中所定义。
  • 增加了检查,以避免在某些病态代码示例上出现指数级编译减速。

工具

Visual Studio Code 扩展

  • 添加了单元测试结果可视化功能。
  • 通过添加 YAML <> Java 代码编辑功能改进了 Micronaut 支持:Micronaut extension added YAML support
  • 添加了多项重构功能。
  • 包含了 Micronaut 项目的 Docker 构建命令。
  • 改进了对 Maven 和 Gradle 多项目构建的支持。

VisualVM

  • 增加了对即将推出的 JDK 16 的支持(#260)。
  • 增加了对新的 Apple M1 处理器 (aarch64) 的支持(#262)。
  • 增加了从先前版本导入插件的支持(#270)。
  • 增加了在堆转储中显示已启用模块列表的功能,该功能取自 jlink 在 JDK 9+ 中创建的模块(#275)。VisualVM dispay list of enabled modules in heap dumps

多语言嵌入

  • 添加了一个新的实验性沙盒选项 --sandbox.MaxHeapMemory=<size>,用于指定客户机应用程序在运行期间可保留的最大堆内存。此功能目前仅在 HotSpot 上受支持。请注意,此功能仍处于实验阶段。(仅在 GraalVM 企业版中可用。)
  • 增加了对字节缓冲区类数据结构的支持。此版本添加了新方法来访问缓冲区值,例如 Value.hasBufferElements()。Java 主机互操作性得到了改进,以处理 java.nio.ByteBuffer 实现,使其像原生客户机语言缓冲区一样工作。此功能可以使用 HostAccess.Builder.allowBufferAccess(boolean) 启用和禁用。对多语言缓冲区的支持可能因语言而异。有关更多详细信息,请参阅各个语言的变更日志。
  • 增加了对可迭代和迭代器类数据结构的支持。这包括使用 Value.isIterator() 和 Value.hasIterator() 检测多语言值是否为迭代器或可迭代对象的新方法。新增了 ProxyIterator 和 ProxyIterable 代理接口以模拟迭代器和可迭代对象。Java 主机互操作性得到了改进,以处理 java.util.Iterator 和 java.util.Iterable 实现,使其像客户机语言值一样工作。此功能可以使用 HostAccess.Builder.allowIteratorAccess(boolean) 和 HostAccess.Builder.allowIterableAccess(boolean) 启用和禁用。客户机语言迭代器现在也可以使用 Value.as(Iterator.class) 映射到 Java 迭代器。此功能在不同语言中的支持可能有所不同。有关更多详细信息,请参阅语言变更日志。
  • 增加了对映射类数据结构的支持(问题 #143)。这包括用于多语言值的新方法,例如 Value.hasHashEntries(),用于查询多语言值是否表示哈希映射类数据结构。新增了 ProxyHashMap 接口以模拟此类值。Java 主机互操作性得到了改进,以处理 java.util.Map 实现,使其看起来像客户机语言哈希映射。此功能可以使用 HostAccess.Builder.allowMapAccess(boolean) 启用和禁用。客户机语言映射现在也可以使用 Value.as(Map.class) 映射到 Java 映射。此功能在不同语言中的支持可能有所不同。有关更多详细信息,请参阅语言变更日志。
  • 添加了 Context.safepoint(),用于在主机方法执行期间协作轮询多语言上下文的线程本地操作。例如,这允许上下文检查中断或取消。

所有更改的详细列表可在变更日志中找到。

Truffle 语言和工具实现

  • 增加了对提交线程本地操作以在语言实现的客户机语言安全点运行的支持(问题 JDK-8263776)。请参阅教程,了解如何在语言或工具实现中调整和使用此功能。
  • InteropLibrary 中为缓冲区元素添加了一个新的互操作性特性,可实现与原生缓冲区的更好集成。
  • InteropLibrary 中添加了一个新的互操作性类型迭代器和可迭代特性,以改进语言之间集合的遍历。
  • InteropLibrary 中为哈希条目添加了一个新的互操作性特性,以改进客户机语言哈希映射之间的互操作性(问题 #143)。
  • 添加了 TruffleInstrument.Env.calculateContextHeapSize(TruffleContext, long, AtomicBoolean) 以计算上下文保留的堆大小。
  • 添加了 @GenerateAOT 以支持 AOT 专门化节点的准备工作。阅读 AOT 教程以开始使用 Truffle 和 AOT 编译。我们还添加了 --engine.CompileAOTOnCreate 选项,以在调用目标创建时触发 AOT 编译。计划在下一个版本中进行更多更改和增强。
  • 添加了 ExactMath.truncate(float) 和 ExactMath.truncate(double) 方法,分别用于移除浮点数或双精度数的十进制部分(向零舍入)。这些方法已被内联。
  • 当语言上下文初始化完成或失败时,向 ContextsListener 添加了几个新事件。
  • 添加了 CompilerDirectives.isExact(Object, Class) 以检查值是否为精确类型。应使用此方法代替 value != null && value.getClass() == exactClass 模式。
  • 添加了 Frame.clear(FrameSlot)。这允许编译器推断局部变量的活跃性。建议语言在适用时使用此方法。
  • 添加了 TruffleLanguage.Env.getLogger(String) 和 TruffleLanguage.Env.getLogger(Class<?>),用于创建上下文绑定的日志记录器。返回的 TruffleLogger 始终使用 Env 上下文中的日志处理程序和选项,并且不依赖于在任何线程上进入。
  • 添加了 TruffleContext.leaveAndEnter(Node, Supplier),用于等待另一个线程而不会触发多线程。
  • 现在,如果已知不适合部分评估的方法在运行时编译中可达,则 Truffle 语言的原生镜像构建会失败。可以使用原生镜像构建器的 -H:-TruffleCheckBlackListedMethods 选项禁用此检查。移除了已弃用的 TruffleLanguage.Env.getTruffleFile(String)TruffleLanguage.Env.getTruffleFile(URI) 方法。
  • 添加了 TruffleContext.isCancelling() 以检查 Truffle 上下文是否正在取消。
  • 为专门化的 DSL @NodeChild 注解添加了新功能:添加了 implicit 和 implicitCreate 属性,以允许父工厂方法隐式创建子节点。
  • 添加了 allowUncached 和 uncached 属性,以允许将 @NodeChild 与 @GenerateUncached 一起使用。
  • 现在可以使用 Profile.disable() 禁用配置文件,并使用 Profile.reset() 重置配置文件。
  • 通过新的 EventBinding.attach() 方法,在 Truffle 插桩中添加了两阶段附加支持。

所有更改的详细列表可在 Truffle 框架变更日志中找到。

联系我们