Nashorn CommandListener $$ NashornJavaAdapter无法转换为CommandListener

时间:2016-11-07 16:51:20

标签: java nashorn

我正在使用Nashorn和Java来制作模块化插件系统。插件将用Javascript编写。一个重要的特性是拥有可以用Javascript代码编写的处理程序。从我开始,我的目标是建立一个简单的命令系统。 javascript实现了一个接口,并调用Java方法来注册该命令。但是,我收到了一个错误。我确保我使用Nashorn(var usingNashorn = typeof importClass !== "function";)返回true。

Javascript:

var CommandListener = Java.extend(Java.type("com.techsdev.scriptengine.listeners.CommandListener"), {
    invoke : function(sender, command, args) {
        java.lang.System.out.println("Received a command: " + command);
    }
});

var listen = function(scriptManager) {
    var listener = new CommandListener();
    scriptManager.registerCommand("plugin name", "test", listener);
}

Java代码: 要调用“listen”:

try {
    engine.eval(new FileReader(f));
    Invocable invocable = (Invocable) engine;
    invocable.invokeFunction("listen", this);
} catch(Exception e) {
    logger.error("Failed to load script "+f.getName(), e);
}

其中'f'是Javascript文件 其中'engine'是Nashorn ScriptEngine 其中'this'是ScriptManager

在ScriptManager类中,此方法负责注册实际命令:

public void registerCommand(String plugin, String command, CommandListener listener) {
        if(commandHandlers.containsKey(command.toLowerCase())) {
            logger.warn("Command "+command+" tried to be registered, but is already registered!");
            return;
        }

        commandHandlers.put(command.toLowerCase(), listener);
}

但是,此代码抛出以下异常:

java.lang.ClassCastException: com.techsdev.scriptengine.listeners.CommandListener$$NashornJavaAdapter cannot be cast to com.techsdev.scriptengine.listeners.CommandListener
    at com.techsdev.scriptengine.JsScriptManager.registerCommand(JsScriptManager.java:168) ~[scriptengine-mod.jar:?]
    at jdk.nashorn.internal.scripts.Script$Recompilation$2$616A$\^eval\_.listen(<eval>:22) ~[?:?]
    at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:625) ~[nashorn.jar:?]
    at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494) ~[nashorn.jar:?]
    at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393) ~[nashorn.jar:?]
    at jdk.nashorn.api.scripting.ScriptObjectMirror.callMember(ScriptObjectMirror.java:199) ~[nashorn.jar:?]
    at jdk.nashorn.api.scripting.NashornScriptEngine.invokeImpl(NashornScriptEngine.java:383) ~[nashorn.jar:?]
    at jdk.nashorn.api.scripting.NashornScriptEngine.invokeFunction(NashornScriptEngine.java:190) ~[nashorn.jar:?]
    at com.techsdev.scriptengine.JsScriptManager.loadFile(JsScriptManager.java:134) [JsScriptManager.class:?]
    at com.techsdev.scriptengine.JsScriptManager.loadFolder(JsScriptManager.java:116) [JsScriptManager.class:?]
    at com.techsdev.scriptengine.JsScriptManager.init(JsScriptManager.java:104) [JsScriptManager.class:?]

如果我遗漏了什么,请告诉我。 提前谢谢。

1 个答案:

答案 0 :(得分:1)

我将从脚本和Java代码中打印com.techsdev.scriptengine.listeners.CommandListener的类加载器。

来自JavaScript:

print(Java.type("com.techsdev.scriptengine.listeners.CommandListener").class.classLoader)

来自Java:

System.out.println(com.techsdev.scriptengine.listeners.CommandListener.class.getClassLoader());

如果两个不同的加载器加载了相同的(完全限定的)命名类字节,那些(运行时)类与JVM的观点不同。如果你从javascript和java代码中看到不同的类加载器,很可能你有类路径/类加载器问题。