I am using Nashorn javascript engine to evaluate all the server side javascript code written in a java application.In order improve performance I am using spring to initialize JsEngine while startup and evaluate & cache all the core tools such as Mustache and some common JS tools. Then each time when screen renders this pre-evaluated JsEngine will be used to evaluate page specific JavaScript code. It works fine for sometime, means it renders the page as expected but start throwing following exception when I keep hitting the same URL
I am not able to find the root cause of the issue.
@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);
}
}
JsEngine used as given below,
public class AppRendererImpl implements AppRenderer {
@Autowired
JsEngine jsEngine;
public String render(){
....
.... //Read source from disk or cache
jsEngine.eval(source);....
}
}
Exception after few render cycles,
Exception:
java.lang.IllegalArgumentException: target and filter types do not match: (ScriptObject)Object, (Object)Object
at java.lang.invoke.MethodHandleStatics.newIllegalArgumentException(MethodHandleStatics.java:115)
at java.lang.invoke.MethodHandles.filterArgument(MethodHandles.java:2416)
at java.lang.invoke.MethodHandles.filterArguments(MethodHandles.java:2403)
at jdk.nashorn.internal.lookup.MethodHandleFactory$StandardMethodHandleFunctionality.filterArguments(MethodHandleFactory.java:277)
at jdk.nashorn.internal.runtime.WithObject.filter(WithObject.java:270)
at jdk.nashorn.internal.runtime.WithObject.fixExpressionCallSite(WithObject.java:249)
at jdk.nashorn.internal.runtime.WithObject.lookup(WithObject.java:169)
at jdk.nashorn.internal.runtime.linker.NashornLinker.getGuardedInvocation(NashornLinker.java:96)
at jdk.internal.dynalink.support.CompositeTypeBasedGuardingDynamicLinker.getGuardedInvocation(CompositeTypeBasedGuardingDynamicLinker.java:176)
at jdk.internal.dynalink.support.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.Script$\^eval_.runScript(:1)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:498)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:206)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:378)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:546)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:528)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:524)
at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:194)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
at com.nube.portal.engines.js.JsEngine.eval(JsEngine.java:111)
at com.nube.portal.engines.html.tags.HtmlTagScript.eval(HtmlTagScript.java:66)
........
I have some custom code added to copy all global objects to another map. This is to facilitate some other requirement I have to access all global object as "nube.". I don't know if this code will create any issues for frequent run. Please keep in mind I am not removing any objects from 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;
}
This code works perfectly when I define JsEngine as Prototype but performance is not good. Do you think this is a bug in Nashorn?