如何在 Java 15 及更高版本中使用 Nashorn?
How to use Nashorn in Java 15 and later?
我有一个现有的 Spring 非模块化引导应用程序,它使用 Nashorn。该应用程序在 Java 14.
上运行良好
添加可用于 Java15 的新 Nashorn 的 Maven 坐标后,应用程序在启动脚本引擎时失败。
public static void main(String[] args) throws ScriptException {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("nashorn");
engine.eval("print('Hello, World!');");
}
错误信息:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "javax.script.ScriptEngine.eval(String)" because "engine" is null
at xxxxx.yyyy.service.JavaScriptServiceImpl.main(JavaScriptServiceImpl.java:52)
是否需要将整个项目模块化才能使用Nashorn?
根据JEP 372, Nashorn had been removed from JDK 15 but you can get latest nashorn from https://search.maven.org/artifact/org.openjdk.nashorn/nashorn-core/15.0/jar
对于 Maven,将以下依赖项包含到您的 pom.xml
<dependency>
<groupId>org.openjdk.nashorn</groupId>
<artifactId>nashorn-core</artifactId>
<version>15.0</version>
</dependency>
对于 Gradle,将下面的依赖项添加到您的 build.gradle
implementation 'org.openjdk.nashorn:nashorn-core:15.0'
不幸的是,Standalone Nashorn is only usable as a JPMS module. So you might need to follow the solution stated in 使其与非模块化应用程序一起工作。
根据给定的 class xxxxx.yyyy.service.JavaScriptServiceImpl
并根据@JornVernee 和@AttilaSzegedi 的反馈,命令行应如下所示
jdk-15.0.1/bin/java -classpath /home/nashorn-helloworld/target/classes --module-path /home/org/openjdk/nashorn/nashorn-core/15.0:/home/org/ow2/asm/asm/7.3.1:/home/org/ow2/asm/asm-analysis/7.3.1:/home/org/ow2/asm/asm-commons/7.3.1:/home/org/ow2/asm/asm-tree/7.3.1/home/org/ow2/asm/asm-util/7.3.1 --add-modules org.openjdk.nashorn xxxxx.yyyy.service.JavaScriptServiceImpl
这里是 Nashorn 维护者。
Spring 引导未将 Nashorn 作为 JPMS 模块加载似乎确实是一个问题。 Nashorn 将自身导出为脚本引擎,可由 javax.script.ScriptEngineManager
通过 "provides" entry in its module-info.java
找到。它不使用通过其 JAR 文件中的相关 META-INF/services/…
条目声明自身的较旧的非模块化导出机制。这意味着如果 JAR 没有作为 JPMS 模块加载,脚本引擎管理器将不会发现它。 (注意:即使它冗余地具有 META-INF/services
条目,也无济于事,因为 Nashorn 依赖于作为模块加载;作为用于 JDK 的代码,它自从Java 9…现在要撤消它有点困难。)
我创建了一个 small test application 来确认是这种情况。我正试图招募一些在 Boot 上工作的人来帮助我弄清这件事的真相。由于 Boot 创建一个胖 JAR 文件并将其所有依赖项打包到其中,然后管理它们的加载,因此这很复杂,因此您不能在启动时“只”自己修改模块路径。
希望有一种方法可以告诉 Boot 将依赖项作为模块加载;我通过 Google 找到它的尝试到目前为止还没有成功。
我刚刚发布了 Nashorn 15.1 这使得 Nashorn 在通过类路径而不是通过模块路径加载时可以正常运行。我用我自己的 Spring 启动应用程序对其进行了测试,它可以正常工作。
我有一个现有的 Spring 非模块化引导应用程序,它使用 Nashorn。该应用程序在 Java 14.
上运行良好添加可用于 Java15 的新 Nashorn 的 Maven 坐标后,应用程序在启动脚本引擎时失败。
public static void main(String[] args) throws ScriptException {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("nashorn");
engine.eval("print('Hello, World!');");
}
错误信息:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "javax.script.ScriptEngine.eval(String)" because "engine" is null
at xxxxx.yyyy.service.JavaScriptServiceImpl.main(JavaScriptServiceImpl.java:52)
是否需要将整个项目模块化才能使用Nashorn?
根据JEP 372, Nashorn had been removed from JDK 15 but you can get latest nashorn from https://search.maven.org/artifact/org.openjdk.nashorn/nashorn-core/15.0/jar
对于 Maven,将以下依赖项包含到您的 pom.xml
<dependency>
<groupId>org.openjdk.nashorn</groupId>
<artifactId>nashorn-core</artifactId>
<version>15.0</version>
</dependency>
对于 Gradle,将下面的依赖项添加到您的 build.gradle
implementation 'org.openjdk.nashorn:nashorn-core:15.0'
不幸的是,Standalone Nashorn is only usable as a JPMS module. So you might need to follow the solution stated in
根据给定的 class xxxxx.yyyy.service.JavaScriptServiceImpl
并根据@JornVernee 和@AttilaSzegedi 的反馈,命令行应如下所示
jdk-15.0.1/bin/java -classpath /home/nashorn-helloworld/target/classes --module-path /home/org/openjdk/nashorn/nashorn-core/15.0:/home/org/ow2/asm/asm/7.3.1:/home/org/ow2/asm/asm-analysis/7.3.1:/home/org/ow2/asm/asm-commons/7.3.1:/home/org/ow2/asm/asm-tree/7.3.1/home/org/ow2/asm/asm-util/7.3.1 --add-modules org.openjdk.nashorn xxxxx.yyyy.service.JavaScriptServiceImpl
这里是 Nashorn 维护者。
Spring 引导未将 Nashorn 作为 JPMS 模块加载似乎确实是一个问题。 Nashorn 将自身导出为脚本引擎,可由 javax.script.ScriptEngineManager
通过 "provides" entry in its module-info.java
找到。它不使用通过其 JAR 文件中的相关 META-INF/services/…
条目声明自身的较旧的非模块化导出机制。这意味着如果 JAR 没有作为 JPMS 模块加载,脚本引擎管理器将不会发现它。 (注意:即使它冗余地具有 META-INF/services
条目,也无济于事,因为 Nashorn 依赖于作为模块加载;作为用于 JDK 的代码,它自从Java 9…现在要撤消它有点困难。)
我创建了一个 small test application 来确认是这种情况。我正试图招募一些在 Boot 上工作的人来帮助我弄清这件事的真相。由于 Boot 创建一个胖 JAR 文件并将其所有依赖项打包到其中,然后管理它们的加载,因此这很复杂,因此您不能在启动时“只”自己修改模块路径。
希望有一种方法可以告诉 Boot 将依赖项作为模块加载;我通过 Google 找到它的尝试到目前为止还没有成功。
我刚刚发布了 Nashorn 15.1 这使得 Nashorn 在通过类路径而不是通过模块路径加载时可以正常运行。我用我自己的 Spring 启动应用程序对其进行了测试,它可以正常工作。