4

JavaScript で定義された関数を Java コードから (Nashorn を使用して) 呼び出し、そこにいくつかのパラメーターを渡す必要があります。Invocable.invokeFunction("Foo", arg1, arg2) を使用する代わりに、インターフェイスを定義し、Invocable にその実装を作成するように要求します。これは、オラクルがここで提案している「Oracle Nashorn の埋め込み」:

package mypackage;
public final class MyClass {
  public interface Composer {
    void compose(final StringBuilder subject, final StringBuilder body);
  }

  public void composeEmail(...) {
      ...
      final ScriptEngineManager engineManager = new ScriptEngineManager();
      final ScriptEngine engine = engineManager.getEngineByName("nashorn");
      engine.eval(scriptText);
      final Invocable invocable = (Invocable) engine;
      final Composer composer = (Composer)invocable.getInterface(Composer);
      composer.compose(subject, body);
      ...
  }
}

問題は、Tomcat で実行されている Web アプリケーションでこれを行っているため、Composer がアプリレベルのクラスローダーによって読み込まれ、nashorn クラスが拡張機能のクラスローダーによって読み込まれることです。そのため、getInterface はTypeError: Can not find a common class loader for ScriptObject と mypackage.Composer を言って失敗します。

それを克服する方法はありますか?もちろん、Composer が実際には ext ローダーであると仮定して (ハックのように)、親クラスローダーに Composer をロードしようとすることもできますが、それには少なくとも 1 つの問題があります。つまり、クラスが見つからないということです。私のパッケージは私の Web アプリケーションに存在し、拡張ローダーはそこに見えません。他に素晴らしいアイデアはありますか?

PSそして今、私はこのメッセージが奇妙であることに気付きました:アプリのクラスローダーが外部クラスローダーに委譲する場合、もちろん後者がそれらの共通のクラスローダーです。たぶん彼らは、ターゲットインターフェースのクラスローダーが実際の実装のクラスローダーと等しくなければならない、または実装のクラスローダーがターゲットのクラスローダーに委譲しなければならない(しかしその逆ではない)と言おうとしていたのでしょうか?

4

1 に答える 1

2

jdk.nashorn.api.scripting.NashornScriptEngineFactoryを実行する代わりに直接のインスタンスを作成し、アプリレベルのローダーを呼び出して渡すことで をengineManager.engineByName()作成します。ScriptEngineNashornScriptEngineFactory.getScriptEngine(ClassLoader appLoader)

于 2015-07-28T16:14:51.220 に答える