来自Nashorn的IllegalArgumentException异常 - 这是Java 8中的错误吗?

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的一个错误吗?

Mar*_*nik 1

要么损坏了持久 JS 上下文中的某些内容,从而违反了优化器的假设,要么这是一个彻头彻尾的错误。该堆栈跟踪显示您的代码去调用一个方法,并且脚本运行时中的代码路径设法到达一个点,在该点处,该函数的优化版本将应用于与其假设不匹配的参数(其参数类型过滤器) )所以它因这个异常而失败。无论您的 JS 代码如何,都不应在一致的运行时中遵循该代码路径。