gpt4 book ai didi

java - 我可以在 war 中捆绑更新版本的 Nashorn 吗?

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:53:10 25 4
gpt4 key购买 nike

除非我遗漏了什么,否则这个版本的 Nashorn 似乎有一些错误:

$ jjs -v
nashorn 1.8.0_45

它在使用 3 位或更多位的多个整数作为属性键时感到窒息:

$ echo 'var c = JSON.parse("{\"123\": \"a\", \"456\": \"b\"}"); print(c["123"])' | jjs; echo
jjs> java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 7

2 位数可以正常工作:

$ echo 'var c = JSON.parse("{\"12\": \"a\", \"45\": \"b\"}"); print(c["12"])' | jjs; echo
jjs> a

3位和2位给出不同的错误:

$ echo 'var c = JSON.parse("{\"123\": \"a\", \"45\": \"b\"}"); print(c["123"])' | jjs; echo
jjs> undefined

一个 3 位数字和一个字符串可以正常工作:

$ echo 'var c = JSON.parse("{\"123\": \"a\", \"foo\": \"b\"}"); print(c["123"])' | jjs; echo
jjs> a

使用这个版本一切正常:

$ jjs -v
nashorn 1.8.0_121

$ echo 'var c = JSON.parse("{\"123\": \"a\", \"456\": \"b\"}"); print(c["123"])' | jjs; echo
jjs> a

无论如何,以上片段只是演示我在我的网络应用程序中遇到的问题的一种方式。我的问题是 - 有没有办法在我的 webapp 中捆绑这个较新版本的 nashorn,这样我就不需要在服务器上请求 java 升级?

最佳答案

这是另一种不需要修改 nashorn jar 的解决方案:

  • bundle nashorn.jar (*) 作为资源文件在你的war中
  • 使用 child-first/parent-last 类加载器,例如 this one
  • 通过此类加载器加载引擎

实现上述方法的示例 servlet,然后尝试使用 JRE 的 Nashorn 和捆绑的 Nashorn 评估您的脚本:

@WebServlet("/nashorn")
public class NashornDemoServlet extends HttpServlet {

private static final ClassLoader CL;

static {
// In my case nashorn.jar is under WEB-INF/classes (resources root)
URL nashornURL = NashornDemoServlet.class.getClassLoader().getResource("nashorn.jar");
CL = new ParentLastURLClassLoader(Collections.singletonList(nashornURL));
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
String script = "var c = JSON.parse(\"{\\\"123\\\": \\\"a\\\", \\\"456\\\": \\\"b\\\"}\"); c[\"123\"]";

ScriptEngine nashorn = new ScriptEngineManager(getClass().getClassLoader()).getEngineByName("nashorn");
try {
Object result = nashorn.eval(script);
out.println("### JRE Nashorn result: " + result);
} catch (Exception e) {
out.println("### JRE Nashorn failed!");
e.printStackTrace(out);
}

try {
Class<?> clazz = CL.loadClass("jdk.nashorn.api.scripting.NashornScriptEngineFactory");
Object factory = clazz.newInstance();
ScriptEngine engine = (ScriptEngine) clazz.getMethod("getScriptEngine").invoke(factory);
Object result = engine.eval(script);
out.println("\n### Bundled Nashorn result: " + result);
} catch (Exception e) {
out.println("### Bundled Nashorn failed!");
e.printStackTrace(out);
}
}
}

在 JRE 8u45 上使用 tomcat 8 的结果:

### JRE Nashorn failed!
java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 7
at java.util.Arrays.rangeCheck(Arrays.java:120)
at java.util.Arrays.fill(Arrays.java:2868)
at jdk.nashorn.internal.runtime.BitVector.setRange(BitVector.java:273)
...
at java.lang.Thread.run(Thread.java:745)

### Bundled Nashorn result: a

网络应用项目树:

enter image description here

在此之前,我还尝试简单地将 nashorn.jar 捆绑在 WEB-INF/lib 下,而不使用自定义类加载器技巧(希望使用通常的 servlet 子级优先类加载器容器就足够了),但这没有用。我想这是因为 Tomcat 遵循 servlet 规范中的这条规则:

Servlet containers that are part of a Java EE product should not allow the application to override Java SE or Java EE platform classes, such as those in java.* and javax.* namespaces, that either Java SE or Java EE do not allow to be modified.

”,看来jdk.* 也属于这一类(无论如何,Tomcat 似乎确实排除了Nashorn)。所以,是的,带上你自己的 ClassLoader 😉

(*) 确保您可以合法地这样做。也许考虑使用来自 OpenJDK 构建的 jar,而不是从 Oracle Java 安装目录复制的。也许考虑将您自己包括在内,而是提供将文件添加到您分发的 war 中的说明(它只是一个 zip 文件)等。

关于java - 我可以在 war 中捆绑更新版本的 Nashorn 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45804312/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com