Я использую Javascript-механизм Nashorn для оценки всего кода JavaScript на стороне сервера, написанного в java-приложении. Для повышения производительности я использую 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);
}
}
JsEngine используется ниже,
public class AppRendererImpl implements AppRenderer {
@Autowired
JsEngine jsEngine;
public String render(){
....
.... //Read source from disk or cache
jsEngine.eval(source);....
}
}
Исключение после нескольких циклов рендеринга,
Исключение:
java.lang.IllegalArgumentException: типы целей и фильтров не соответствуют: (ScriptObject) Object, (Object) Object
в java.lang.invoke.MethodHandleStatics.newIllegalArgumentException(MethodHandleStatics.java:115)
в java.lang.invoke.MethodHandles.filterArgument(MethodHandles.java:2416)
в java.lang.invoke.MethodHandles.filterArguments(MethodHandles.java:2403)
в jdk.nashorn.internal.lookup.MethodHandleFactory $СтандартныеMethodHandleFunctionality.filterArguments(MethodHandleFactory.java:277)
в jdk.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.support.CompositeGuardingDynamicLinker.getGuardedInvocation(CompositeGuardingDynamicLinker.java:124)
в jdk.internal.dynalink.support.LinkerServicesImpl.getGuardedInvocation(LinkerServicesImpl.java:144)
на jdk.internal.dynalink.DynamicLinker.relink(DynamicLinker.java:232)
в jdk.nashorn.internal.scripts.Script $\ ^ eval _._ L6 $_L8 (: 21)
в jdk.nashorn.internal.scripts.Script $\ ^ eval _._ L6 $_L40 (: 41)
в jdk.nashorn.internal.scripts.Script $\ ^ eval_.runScript(: 1)
в jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:498)
в jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:206)
в jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:378)
в jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:546)
в jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:528)
в jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:524)
в jdk.nashorn.api.scripting.NashornScriptEngine.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". Я не знаю, создаст ли этот код какие-либо проблемы для частого запуска. Имейте в виду, что я не удаляю какие-либо объекты из контекста.
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;
}
Этот код отлично работает, когда я определяю JsEngine как прототип, но производительность не очень хорошая. Как вы думаете, это ошибка в Нашорне?