kam*_*oor 14 java spring java-8 nashorn
我正在使用Nashorn javascript引擎来评估在java应用程序中编写的所有服务器端javascript代码.为了提高性能,我在启动时使用spring初始化JsEngine并评估和缓存所有核心工具,如Mustache和一些常见的JS工具.然后每次屏幕渲染时,这个预先评估的JsEngine将用于评估特定于页面的JavaScript代码.它在某些时候工作正常,意味着它按预期呈现页面,但在我持续点击相同的URL时开始抛出异常
我无法找到问题的根本原因.
@Component
public class JsEngine {
private ScriptEngine scriptEngine;
@PostConstruct
public void init() throws ScriptException, IOException{
scriptEngine = new ScriptEngineManager().getEngineByName("nashorn");
this.cacheAllCoreEngines();
for(String key: defaultEngineSource.keySet()){
scriptEngine.eval(defaultEngineSource.get(key));
}
}
private void cacheAllCoreEngines()throws IOException{
//read all core files such as mustache, etc.
defaultEngineSource.put("mustache", FileUtil.readFileFromDisk("<actual path..>/mustache.js"));
}
public Object eval(String source) throws ScriptException{
.... code to handle exceptions
return scriptEngine.eval (source);
}
}
Run Code Online (Sandbox Code Playgroud)
JsEngine如下所示,
public class AppRendererImpl implements AppRenderer {
@Autowired
JsEngine jsEngine;
public String render(){
....
.... //Read source from disk or cache
jsEngine.eval(source);....
}
}
Run Code Online (Sandbox Code Playgroud)
几个渲染周期后的异常,
异常:
java.lang.IllegalArgumentException异常:目标和过滤器类型不匹配:(ScriptObject)对象,(对象)对象
在java.lang.invoke.MethodHandleStatics.newIllegalArgumentException(MethodHandleStatics.java:115)
在java.lang.invoke.MethodHandles .filterArgument(MethodHandles.java:2416 ) 位于jdk的jdk.nashorn.internal.lookup.MethodHandleFactory $ StandardMethodHandleFunctionality.filterArguments(MethodHandleFactory.java:277)的
java.lang.invoke.MethodHandles.filterArguments(MethodHandles.java:2403). nashorn.internal.runtime.WithObject.filter(WithObject.java:270) 在jdk.nashorn.internal.runtime.WithObject.fixExpressionCallSite(WithObject.java:249) 在jdk.nashorn.internal.runtime.WithObject.lookup(WithObject.的java:169) 在jdk.nashorn.internal.runtime.linker.NashornLinker.getGuardedInvocation(NashornLinker.java:96) 在jdk.internal.dynalink.support.CompositeTypeBasedGuardingDynamicLinker.getGuardedInvocation(CompositeTypeBasedGuardingDynamicLinker.java:176) 在jdk.internal.dynalink .suppor t.CompositeGuardingDynamicLinker.getGuardedInvocation(CompositeGuardingDynamicLinker.java:124) at jdk.internal.dynalink.support.LinkerServicesImpl.getGuardedInvocation(LinkerServicesImpl.java:144) at jdk.internal.dynalink.DynamicLinker.relink(DynamicLinker.java:232) at jdk .nashorn.internal.scripts.Script $\^ eval _._ L6 $ _L8(:21) at jdk.nashorn.internal.scripts.Script $\^ eval _._ L6 $ _L40(:41) at jdk.nashorn.internal.scripts .d $\^ eval_.runScript(:1) at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:498) at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:206) 在jdk.nashorn.api上的jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:378) jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:546) at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl (NashornScriptEngine.java:528) 在jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:524) 在jdk.nashorn.api.scripting.NashornScriptEng ine.eval(NashornScriptEngine.java:194) 在javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264) 在com.nube.portal.engines.js.JsEngine.eval(JsEngine.java:111) 在com.nube .portal.engines.html.tags.HtmlTagScript.eval(HtmlTagScript.java:66) ........
我添加了一些自定义代码以将所有全局对象复制到另一个地图.这是为了促进我必须以"nube"访问所有全局对象的一些其他要求.我不知道这段代码是否会为频繁运行造成任何问题.请记住,我没有从Context中删除任何对象.
public void movePublicObjects(String prefix) throws NubeException{
Bindings b1 = scriptEngine.getContext().getBindings(ScriptContext.ENGINE_SCOPE);
Map<String, Object> nubeObjects = new HashMap<String, Object>();
for(Entry<String, Object> entry: b1.entrySet()){
if(!entry.getKey().equals("nube")){
nubeObjects.put(entry.getKey(), entry.getValue());
}
}
b1.put("nube", nubeObjects);
return;
}
Run Code Online (Sandbox Code Playgroud)
当我将JsEngine定义为Prototype但性能不佳时,此代码可以正常工作.你觉得这是Nashorn的一个错误吗?
要么损坏了持久 JS 上下文中的某些内容,从而违反了优化器的假设,要么这是一个彻头彻尾的错误。该堆栈跟踪显示您的代码去调用一个方法,并且脚本运行时中的代码路径设法到达一个点,在该点处,该函数的优化版本将应用于与其假设不匹配的参数(其参数类型过滤器) )所以它因这个异常而失败。无论您的 JS 代码如何,都不应在一致的运行时中遵循该代码路径。