- 适用于 JDK 24 的 GraalVM(最新)
- 适用于 JDK 25 的 GraalVM(早期访问)
- 适用于 JDK 21 的 GraalVM
- 适用于 JDK 17 的 GraalVM
- 存档
- 开发构建
Node.js 和 Java 嵌入之间的差异
GraalVM 提供了一个完全兼容 ECMAScript 2024 的 JavaScript 运行时。因此,它可以在各种嵌入场景中运行 JavaScript 代码,包括 Oracle Database、任何基于 Java 的应用程序以及 Node.js。
根据嵌入场景的不同,应用程序可以访问不同的内置功能。例如,使用 GraalVM 的 bin/node
可执行文件运行的 Node.js 应用程序可以访问所有 Node.js 的 API,包括内置的 Node.js 模块,如 fs
、http
等。相反,嵌入在 Java 应用程序中的 JavaScript 代码只能访问有限的功能(通过 Context 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 的多语言 Context
强制执行“不共享任何内容”的并行模型:两个并发的 Java 线程不能同时访问任何 JavaScript 值。为了利用并行执行,必须从多个线程创建并执行多个上下文。
- 在 Node.js 模式下,可以使用 Node.js 的 Worker threads API 创建多个上下文。Worker threads API 确保两个并行上下文之间不会发生共享。
- 在 Java 中,可以从多个线程执行多个上下文。只要一个上下文不被两个线程同时访问,并行执行就能安全进行。
有关 GraalJS 中并行执行的更多详细信息,请参阅这篇博客文章。
Java 库 #
Java 库可以通过内置的 Java
对象从 GraalJS 访问。为了使 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 模块可用的内置机制加载。CommonJS 模块在 Java 模式下通过实验性选项支持。
有关 JavaScript 模块的更多详细信息,请参阅模块。