Java 与 JavaScript 的“桥梁”
无论使用哪种方法,其核心都是一个 “脚本引擎”,这是一个由 Java 实现的程序,能够解析和执行 JavaScript 代码,Java 通过 javax.script API(也称为 Nashorn)或新的 GraalVM 来提供这个引擎。

使用 GraalVM (推荐,现代且高性能)
GraalVM 是 Oracle 推出的一项革命性技术,它是一个高性能的通用虚拟机,支持多种语言(包括 JavaScript、Python、Ruby 等),它的 JavaScript 引擎 GraalJS 是 Nashorn 的继任者,性能更好,功能更全,并且是 Java 21+ 的默认 JavaScript 引擎。
准备工作
你需要将 GraalVM 的 JavaScript 依赖项添加到你的项目中。
Maven (pom.xml):
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js</artifactId>
<version>23.1.0</version> <!-- 请使用最新的版本 -->
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js-scriptengine</artifactId>
<version>23.1.0</version>
</dependency>
Gradle (build.gradle):

implementation 'org.graalvm.js:js:23.1.0' // 请使用最新的版本 implementation 'org.graalvm.js:js-scriptengine:23.1.0'
基本调用示例
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class GraalVMExample {
public static void main(String[] args) {
// 1. 脚本引擎管理器
ScriptEngineManager engineManager = new ScriptEngineManager();
// 2. 获取 GraalJS 引擎 (会自动查找 classpath 中的 GraalVM)
ScriptEngine engine = engineManager.getEngineByName("graal.js");
// 或者直接使用 "js" (推荐)
// ScriptEngine engine = engineManager.getEngineByName("js");
if (engine == null) {
System.err.println("GraalJS 引擎未找到,请确保已添加依赖。");
return;
}
try {
// 3. 执行简单的 JavaScript 表达式
System.out.println("--- 执行简单表达式 ---");
Object result = engine.eval("10 + 15");
System.out.println("10 + 15 = " + result); // 输出: 25
// 4. 执行多行 JavaScript 代码
System.out.println("\n--- 执行多行代码 ---");
engine.eval("var message = 'Hello from JavaScript!';");
engine.eval("function greet(name) { return 'Hello, ' + name + '!'; }");
// 5. 调用 JavaScript 函数并传递参数
Object greeting = engine.eval("greet('Java World');");
System.out.println(greeting); // 输出: Hello, Java World!
// 6. 从 Java 向 JavaScript 传递变量
System.out.println("\n--- 传递变量 ---");
String javaVar = "GraalVM";
engine.eval("var receivedVar = '" + javaVar + "';");
Object received = engine.eval("console.log('Received in JS: ' + receivedVar); receivedVar;");
System.out.println("从 JS 返回的变量: " + received);
// 7. 从 JavaScript 向 Java 传递对象 (更高级的用法)
System.out.println("\n--- 传递复杂对象 ---");
engine.eval("var user = { name: 'Alice', age: 30 };");
// eval 返回的是 JavaScript 对象,GraalVM 会自动将其转换为对应的 Java 对象
Object userObj = engine.eval("user;");
System.out.println("从 JS 获取的 Java 对象: " + userObj.getClass().getName());
System.out.println("用户名: " + ((java.util.Map) userObj).get("name"));
System.out.println("年龄: " + ((java.util.Map) userObj).get("age"));
} catch (ScriptException e) {
e.printStackTrace();
}
}
}
GraalVM 的优势
- 高性能:JIT 编译使其性能远超 Nashorn。
- 全 ES6+ 支持:支持最新的 JavaScript 语法。
- 与 Java 21+ 深度集成:是 Java 21 及以后版本默认的 JavaScript 引擎。
- Polyglot(多语言):同一个虚拟机中可以无缝切换执行 JavaScript、Python 等语言。
使用 Nashorn (传统方法,Java 8-17)
Nashorn 是 Java 8 引入的默认 JavaScript 引擎,用于取代旧的 Rhino,它在 Java 8 到 Java 17 中是标准,GraalVM 出现后,Nashorn 已被标记为“废弃”(deprecated)。
准备工作
- Java 8+ 环境:Nashorn 是 JDK 自带的,无需额外依赖。
- 如果你使用 Java 11+,Nashorn 默认是模块化的,可能需要添加
--add-modules=java.scripting来启用。
基本调用示例
代码与 GraalVM 的示例几乎完全相同,因为它们都遵循 javax.script API。
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class NashornExample {
public static void main(String[] args) {
// 1. 脚本引擎管理器
ScriptEngineManager engineManager = new ScriptEngineManager();
// 2. 获取 Nashorn 引擎
// 注意:Nashorn 的名称是 "nashorn"
ScriptEngine engine = engineManager.getEngineByName("nashorn");
if (engine == null) {
System.err.println("Nashorn 引擎未找到。");
return;
}
try {
// 3. 执行代码 (与 GraalVM 示例相同)
System.out.println("--- 执行简单表达式 ---");
Object result = engine.eval("10 + 15");
System.out.println("10 + 15 = " + result);
System.out.println("\n--- 执行多行代码 ---");
engine.eval("var message = 'Hello from Nashorn!';");
engine.eval("function greet(name) { return 'Hello, ' + name + '!'; }");
Object greeting = engine.eval("greet('Java World');");
System.out.println(greeting);
} catch (ScriptException e) {
e.printStackTrace();
}
}
}
Nashorn 的局限性
- 性能不如 GraalVM。
- ES6+ 支持不完整:不支持
let/const、箭头函数、类等现代特性。 - 已废弃:官方建议迁移到 GraalVM。
使用 Rhino (旧版方法)
Rhino 是 Nashorn 之前的 JavaScript 引擎,由 Mozilla 开发,它非常稳定,但已经不再被积极维护,并且从 Java 11 开始,它不再是 JDK 的一部分。
准备工作
你需要手动添加 Rhino 的依赖。

Maven (pom.xml):
<dependency>
<groupId>org.mozilla</groupId>
<artifactId>rhino</artifactId>
<version>1.7.14</version> <!-- 使用一个较新的稳定版本 -->
</dependency>
基本调用示例
Rhino 的 API 与 javax.script 略有不同,但核心思想一致。
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
public class RhinoExample {
public static void main(String[] args) {
// 1. 创建一个 Rhino 上下文
Context context = Context.enter();
try {
// 2. 初始化作用域 (类似于 JavaScript 的全局对象)
Scriptable scope = context.initStandardObjects();
// 3. 执行脚本
System.out.println("--- 执行简单表达式 ---");
Object result = context.evaluateString(scope, "10 + 15", "<cmd>", 1, null);
System.out.println("10 + 15 = " + result);
System.out.println("\n--- 执行多行代码 ---");
context.evaluateString(scope, "var message = 'Hello from Rhino!';", "<cmd>", 1, null);
context.evaluateString(scope, "function greet(name) { return 'Hello, ' + name + '!'; }", "<cmd>", 1, null);
Object greeting = context.evaluateString(scope, "greet('Java World');", "<cmd>", 1, null);
System.out.println(greeting);
// 4. 在作用域中设置 Java 变量
System.out.println("\n--- 传递变量 ---");
String javaVar = "Rhino";
ScriptableObject.putProperty(scope, "javaVar", javaVar);
context.evaluateString(scope, "console.log('Received in JS: ' + javaVar);", "<cmd>", 1, null);
} finally {
// 5. 退出上下文
Context.exit();
}
}
}
Rhino 的特点
- 非常稳定:历史悠久,经过充分测试。
- API 不同:不使用
javax.script,有自己的 API,代码更“底层”。 - 过时:除非有特殊的历史遗留项目需求,否则不推荐使用。
总结与选择
| 特性 | GraalVM (推荐) | Nashorn (传统) | Rhino (旧版) |
|---|---|---|---|
| 状态 | 现代、活跃 | 已废弃 (Java 8-17) | 过时、不推荐 |
| 性能 | 非常高 | 较好 | 一般 |
| JS 版本支持 | ES6+ 全支持 | ES5/部分 ES6 | ES5 |
| Java 版本 | 任何版本,Java 21+ 默认 | Java 8 - Java 17 | Java 7 及以前 |
| 依赖 | 需要手动添加 js 和 js-scriptengine |
JDK 自带 (Java 8-17) | 需要手动添加 rhino |
| API | javax.script |
javax.script |
Rhino 自定义 API |
| 推荐场景 | 所有新项目,追求性能和现代 JS 语法 | 维护旧项目 (Java 8-17) | 维护非常老的遗留项目 |
最终建议:
- 对于任何新的 Java 项目,请毫不犹豫地选择 GraalVM,它是未来,性能最好,功能最全。
- 如果你正在维护一个使用 Java 8 到 Java 17 的项目,并且无法升级,Nashorn 是你的选择。
- 除非你有一个无法迁移的古老系统,否则请避免使用 Rhino。
