- 适用于 JDK 23 的 GraalVM(最新版本)
- 适用于 JDK 24 的 GraalVM(抢先体验版)
- 适用于 JDK 21 的 GraalVM
- 适用于 JDK 17 的 GraalVM
- 存档
- 开发者构建版
Node.js 和 Java 嵌入之间的差异
GraalVM 提供了一个完全符合 ECMAScript 2024 标准的 JavaScript 运行时。因此,它可以在各种嵌入场景中运行 JavaScript 代码,包括 Oracle 数据库、任何基于 Java 的应用程序和 Node.js。
根据嵌入场景的不同,应用程序可以访问不同的内置功能。例如,使用 GraalVM 的 bin/node
可执行文件执行的 Node.js 应用程序可以访问所有 Node.js 的 API,包括内置的 Node.js 模块,例如 fs
、http
等。相反,嵌入在 Java 应用程序中的 JavaScript 代码只能访问有限的功能,这些功能通过 上下文 API 指定,并且无法访问 Node.js 内置模块。
本指南描述了 Node.js 应用程序和嵌入在 Java 应用程序中的 JavaScript 之间的主要区别。
上下文创建 #
GraalVM 中的 JavaScript 代码可以使用执行上下文来执行。
在 Java 应用程序中,可以使用 Context
API 创建新的上下文。可以以多种方式配置新的上下文,配置选项包括公开对 Java 类访问权限、允许访问 IO 等。可以在 API 文档 中找到上下文创建选项的列表。在这种情况下,可以通过使用 GraalVM 的 Polyglot Bindings
将 Java 类公开给 JavaScript。
在 Node.js 应用程序中,执行应用程序的 GraalVM Context
由 Node.js 运行时预先初始化,用户应用程序无法对其进行配置。在这种情况下,可以通过使用 bin/node
命令的 --vm.cp=
命令行选项将 Java 类公开给 Node.js 应用程序,如下所述。
Java 交互操作性 #
JavaScript 应用程序可以使用内置的 Java
对象与 Java 类进行交互。此对象在 js
和 node
启动器中默认可用,但仅在 JVM 独立模式下(名称中包含 -jvm
)才能访问 Java 类。
当使用 Polyglot API 嵌入 JavaScript 时,您必须在 Context.Builder
中显式启用主机访问(allowHostAccess
、allowHostClassLookup
)。有关 JavaScript-Java 交互操作性的更多详细信息,请参阅 Java 交互操作性指南。
多线程 #
运行 JavaScript 的 polyglot Context
采用“无共享”并行模型:两个并发 Java 线程不能同时访问任何 JavaScript 值。为了利用并行执行,必须从多个线程创建和执行多个上下文。
- 在 Node.js 模式下,可以使用 Node.js 的 Worker 线程 API 创建多个上下文。Worker 线程 API 确保两个并行上下文之间不会发生共享。
- 在 Java 中,可以从多个线程执行多个上下文。只要一个上下文没有被两个线程同时访问,并行执行就会安全地发生。
有关 GraalJS 中并行执行的更多详细信息,请参阅 这篇博文。
Java 库 #
可以通过 Java
内置对象从 GraalJS 访问 Java 库。为了让 Java 库可以从 Context
访问,需要将它的 JAR 文件添加到类路径中。可以通过以下方式完成此操作。
- 在 Node.js 模式下,可以使用
--vm.cp
选项修改类路径。 - 在 Java 中,可以使用默认的 Java
-cp
选项。
在 命令行选项 中了解更多信息。
JavaScript 包和模块 #
许多流行的 JavaScript 模块(例如在 npm
包注册表中提供的模块)既可以从 Node.js 使用,也可以从 Java 使用。
- 在 Node.js 模式下,JavaScript 模块由 Node.js 运行时处理。因此,GraalJS 支持 Node.js 支持的所有模块(包括 ES 模块、CommonJS 模块和原生模块)。
- 在 Java 模式下,GraalJS 可以执行任何不依赖于原生 Node.js 内置模块(例如
fs
、http
等)的 JavaScript 模块或包。可以使用包捆绑器加载模块,也可以使用可用的内置机制加载 ES 模块。在 Java 模式下,CommonJS 模块在实验性选项下受支持。
有关 JavaScript 模块的更多详细信息,请参阅 模块。