Nashorn和OSGi:invocable.getInterface():找不到ScriptObject和MyInterface的公共类加载器

时间:2016-07-21 14:37:39

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

在从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的其他或其他解决方法的任何想法?

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

问题不在于代码。问题出在应用服务器上。 我使用的是JBoss 6.4.0 Application Server,问题是它在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"/>