作者:溪龙2012_753 | 来源:互联网 | 2023-01-22 10:02
除非我在这里遗漏了一些东西,否则这个版本的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中遇到的问题的方法.我的问题是 - 有没有办法在我的webapp中捆绑这个较新版本的nashorn,这样我就不需要在服务器上请求java升级了?
1> Hugues M...:
这是另一个不需要修改nashorn jar的解决方案:
捆绑nashorn.jar
(*)作为战争中的资源文件
使用child-first/parent-last类加载器,例如这个
通过此类加载器加载引擎
实现上述方法的示例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
Web应用程序项目树:
在此之前,我还尝试简单地nashorn.jar
在WEB-INF/lib
没有自定义类加载器技巧的情况下进行捆绑(希望servlet容器的通常的子级优先级加载器就足够了),但这不起作用.我想这是因为Tomcat遵循servlet规范中的这条规则:
Servlet容器是一个Java EE产品的一部分,不应该允许应用程序重写的Java SE或Java EE平台类,如在java.*
和javax.*
命名空间,要么的Java SE或Java EE不允许进行修改.
" 比如 ",所以似乎jdk.*
也属于那个类别(无论如何,Tomcat似乎确实排除了Nashorn).所以是的,带上你自己的ClassLoader
(*)确保你可以合法地做到这一点.也许考虑使用OpenJDK构建中的jar,而不是从Oracle Java安装目录中复制.也许考虑不包括你自己,但提供说明将文件添加到你分发的战争(它只是一个zip文件),等等.