如何在Java15及更高版本中使用Nashorn?

如何在Java15及更高版本中使用Nashorn?,java,nashorn,java-15,Java,Nashorn,Java 15,我有一个现有的Spring Boot应用程序,它是非模块化的,并且使用Nashorn。该应用程序在Java14上运行良好 添加Java15可用的新Nashorn的Maven坐标后,应用程序在启动脚本引擎时失败 public static void main(String[] args) throws ScriptException { ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine eng

我有一个现有的Spring Boot应用程序,它是非模块化的,并且使用Nashorn。该应用程序在Java14上运行良好

添加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?

根据,Nashorn已从JDK 15中删除,但您可以从

对于Maven,在
pom.xml

<dependency>
  <groupId>org.openjdk.nashorn</groupId>
  <artifactId>nashorn-core</artifactId>
  <version>15.0</version>
</dependency>
不幸的是,它只能用作JPMS模块。因此,您可能需要遵循中所述的解决方案,使其与非模块化应用程序一起工作

从给定的类
xxxxx.yyy.service.JavaScriptServiceImpl
,并根据@jornverne和@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

这里是纳肖恩维修工

springboot没有将Nashorn作为JPMS模块加载,这确实是一个问题。Nashorn将自己导出为脚本引擎,由
javax.script.ScriptEngineManager
通过。它不使用旧的、非模块化的导出机制,即通过JAR文件中的相关
META-INF/services/…
条目声明自己。这意味着,如果JAR没有作为JPMS模块加载,脚本引擎管理器将不会发现它。(注意:即使它冗余了
META-INF/services
条目,也不会有什么帮助,因为Nashorn依赖于作为模块加载;作为JDK附带的代码,它从Java 9开始就是一个模块……现在要撤销它有些困难。)

我创建了一个报告,证实了这一点。我正试图招募一些在Boot上工作的人来帮我弄清这件事的真相。Boot创建了一个胖JAR文件并将其所有依赖项打包到该文件中,然后管理它们的加载,这一点很复杂,因此启动时您不能“仅仅”修改模块路径


希望有一种方法可以告诉Boot将依赖项作为模块加载;到目前为止,我试图通过谷歌找到它的努力还没有取得成效。

我刚刚发布了一个新版本,它使Nashorn在通过类路径而不是模块路径加载时能够正常工作。我用我自己的一个小型Spring Boot应用程序对它进行了测试,它可以正常工作。

JavaNashorn已在Java15中删除(请参阅)。自Java 11以来,您应该得到一个警告。@jornverne我尝试了--add modules as args,但它不起作用jdk-15.0.1/bin/Java-classpath/home/nashorn helloworld/target/classes helloworld--module path/home/org/openjdk/nashorn/nashorn-core/15.0/nashorn-core-15.0.jar:/home/org/ow2/asm/7.3.1/asm-7.3.1.jar:/home/org/ow2/asm/asm-commons/7.3.1/asm-commons-7.3.1.jar:/home/org/ow2/asm/asm/tree/7.3.1/7.1/asm-tree/7.3.1/7.3.1.jar:/home/org/ow2/asm/asm/asm/util/7.3.1/7.1/7.1/7.3.1/7.3.1.1/7.1.1.jar/7.3.1/7.1.1.jar/7org.ow2.asm.asm-commons--添加模块org.ow2.asm.asm-tree--添加模块org.ow2.asm.asm-util@AswathMurugan您只需要将
--addmodules org.openjdk.nashorn
作为程序参数传递
--module path
参数,而不是作为VM选项传递
HelloWorld
,我假设它是您的主类,谢谢@jornverne它成功了另外,
--module path
是一个目录列表;您只需要列出模块化JAR文件所在的目录,而不是JAR文件本身。很抱歉有点愚蠢,但我刚刚升级到JDK 15,我认为只需将依赖项添加到org.openjdk.nashorn:nashorn core:15.2就足够了。但是,我一直在ClassFilter类上得到NoClassDefFound错误。在这种情况下,我认为我不需要添加模块选项,这是不对的吗?似乎很有魅力,谢谢阿提拉。首先,我尝试在没有模块的情况下使用独立的Nashorn 15.2,它似乎陷入了无限等待/循环,没有出现错误
ScriptEngineFactory sef=new org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory();ScriptEngine nashornEngine=sef.getScriptEngine()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