【问题标题】:Nashorn and OSGi: invocable.getInterface() : Can not find a common class loader for ScriptObject and MyInterfaceNashorn 和 OSGi:invocable.getInterface():找不到 ScriptObject 和 MyInterface 的通用类加载器
【发布时间】:2016-11-25 05:18:38
【问题描述】:

在从 IBM Java 7 更新到 8 之前,以下代码曾在 Equinox OSGi 环境中工作:

ScriptEngineManager manager = new ScriptEngineManager(getClass().getClassLoader());
ScriptEngine engine = manager.getScriptEngineManager().getEngineByExtension("js");
engine.eval("<... js code ...>");
((Invocable) engine).getInterface(MyInterface.class) // ECMAScript exception

在之前的设置中,我使用 Rhino 作为引擎,它现在不再注册为可用的 ScriptEngineFactory,但仍在类路径中,只有“Oracle Nashorn”。

更新到 IBM Java 8(包括 Nashorn)后,出现以下异常:

    ECMAScript Exception: TypeError: Can not find a common class loader for ScriptObject and MyInterface.
        at jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:69)
        at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:225)
        at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:197)
        at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:184)
        at jdk.nashorn.internal.runtime.linker.AdaptationResult.typeError(AdaptationResult.java:82)
        at jdk.nashorn.internal.runtime.linker.JavaAdapterFactory$AdapterInfo.getAdapterClass(JavaAdapterFactory.java:326)
        at jdk.nashorn.internal.runtime.linker.JavaAdapterFactory.getAdapterClassFor(JavaAdapterFactory.java:162)
        at jdk.nashorn.internal.runtime.linker.JavaAdapterFactory.getAdapterClassFor(JavaAdapterFactory.java:148)
        at jdk.nashorn.internal.runtime.linker.JavaAdapterFactory.getConstructor(JavaAdapterFactory.java:202)
        at jdk.nashorn.api.scripting.NashornScriptEngine.getInterfaceInner(NashornScriptEngine.java:291)
        at jdk.nashorn.api.scripting.NashornScriptEngine.getInterface(NashornScriptEngine.java:216)
        ...

Nashorn 尝试通过以下方式检查 jdk.nashorn.internal.runtime.ScriptFunction (Ext ClassLoader) 的类加载器是否可以加载给定的接口 (Bundle ClassLoader),反之亦然:

Class.forName(classBName, false, clazzA.getLoader()) == classB;

任何想法如何配置 OSGi 以让一个类加载器看到另一个或其他解决方法,以便在 Java 8 + OSGi 上使用 Nashorn?

【问题讨论】:

    标签: java-8 osgi classloader nashorn ibm-jdk


    【解决方案1】:

    问题不在于代码。问题出在应用程序服务器上。 我使用的是 JBoss 6.4.0 应用服务器,问题是它在 EAP_HOME\modules\system\layers\base\sun\jdk\main 下的 module.xml 文件中没有 nashorn 路径。我将缺少的 nashorn 路径添加到上述路径中提到的 module.xml 文件中,它解决了我的问题。您也可以使用 Jboss 7.0 解决此问题,因为它默认具有 nashorn 路径。

    缺少 nashorn 路径

                    <path name="jdk/nashorn/api/scripting"/>
                    <path name="jdk/nashorn/api/scripting/resources"/>
                    <path name="jdk/nashorn/internal/codegen"/>
                    <path name="jdk/nashorn/internal/codegen/types"/>
                    <path name="jdk/nashorn/internal/ir"/>
                    <path name="jdk/nashorn/internal/ir/annotations"/>
                    <path name="jdk/nashorn/internal/ir/debug"/>
                    <path name="jdk/nashorn/internal/ir/visitor"/>
                    <path name="jdk/nashorn/internal/lookup"/>
                    <path name="jdk/nashorn/internal/objects"/>
                    <path name="jdk/nashorn/internal/objects/annotations"/>
                    <path name="jdk/nashorn/internal/parser"/>
                    <path name="jdk/nashorn/internal/runtime"/>
                    <path name="jdk/nashorn/internal/runtime/arrays"/>
                    <path name="jdk/nashorn/internal/runtime/linker"/>
                    <path name="jdk/nashorn/internal/runtime/options"/>
                    <path name="jdk/nashorn/internal/runtime/regexp"/>
                    <path name="jdk/nashorn/internal/runtime/regexp/joni"/>
                    <path name="jdk/nashorn/internal/runtime/resources"/>
                    <path name="jdk/nashorn/internal/runtime/resources/fx"/>
                    <path name="jdk/nashorn/internal/runtime/scripts"/>
                    <path name="jdk/nashorn/internal/tools"/>
                    <path name="jdk/nashorn/internal/tools/resources"/>
                    <path name="jdk/internal/dynalink"/>
                    <path name="jdk/internal/dynalink/beans"/>
                    <path name="jdk/internal/dynalink/linker"/>
                    <path name="jdk/internal/dynalink/support"/>
    

    【讨论】:

      【解决方案2】:

      根据 Oracle Docs,您可以像以下示例一样初始化引擎:

      ScriptEngineManager engineManager = new ScriptEngineManager();
          ScriptEngine engine = engineManager.getEngineByName("nashorn");
          engine.eval(new FileReader("src/sample2/xyz.js"));
          Invocable invocable = (Invocable) engine;
      

      【讨论】:

      • 感谢您的回答。我尝试使用 null 并且没有任何类加载器作为参数来初始化 ScriptEngineManager,但在 Invocable 上调用 getInterface() 时仍然遇到相同的异常。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-30
      • 2022-01-20
      • 2014-08-20
      • 2017-03-11
      • 1970-01-01
      • 2013-02-28
      • 1970-01-01
      相关资源
      最近更新 更多