Java 7プロジェクトがあり、さまざまな機能のスクリプト作成にJavascriptを多く使用しています。これまで、スクリプトエンジンとしてRhinoを使用していました。次にJava 8に移動したいと思います。これは、RhinoをNashornに置き換えることも意味します。
NashornはRhinoとどの程度互換性がありますか?ドロップイン置換として使用できますか、または一部のスクリプトが動作しなくなり、新しいエンジンに移植する必要があると期待できますか? NashornでサポートされていないRhinoの一般的に使用される機能はありますか?
1つの問題は、NashornがデフォルトでimportPackage(com.organization.project.package);
を使用してグローバルスコープにJavaパッケージ全体をインポートできない
ただし、簡単な回避策があります。この行をスクリプトに追加すると、Rhinoの古い動作を有効にできます。
_load("nashorn:mozilla_compat.js");
_
私が遭遇した別の問題は、Javaとjavascriptの間でデータを渡すときの特定のタイプ変換です。たとえば、Javascript配列をJavaはList
にキャストできなくなりましたが、_Map<String, Object>
_にキャストできます。回避策として、Javascript配列をJava = Java.to(array, Java.type("Java.util.List"))
を使用してJavascriptコードにリストする
JDK 8でimportClassメソッドを使用するには、次のコマンドを追加する必要があります。
load("nashorn:mozilla_compat.js");
ただし、この変更はJDK 7での実行に影響します(JDKはloadメソッドをサポートしていません)。
両方のSDKの互換性を維持するために、try/catch句を追加してこの問題を解決しました。
try{
load("nashorn:mozilla_compat.js");
}catch(e){
}
Nashornは、内部クラスがprivateと宣言されている場合、Rhinoが実行できた内部クラスにアクセスできません。
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class Test {
public static void main(String[] args) {
Test test = new Test();
test.run();
}
public void run() {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript");
Inner inner = new Inner();
engine.put("inner", inner);
try {
engine.eval("function run(inner){inner.foo(\"test\");} run(inner);");
} catch (ScriptException e) {
e.printStackTrace();
}
}
private class Inner {
public void foo(String msg) {
System.out.println(msg);
}
}
}
Java8では、このコードは次の例外をスローします。
javax.script.ScriptException: TypeError: kz.test.Test$Inner@117cd4b has no such function "foo" in <eval> at line number 1
at jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.Java:564)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.Java:548)
Rhinoには「in()」と呼ばれる関数に問題がないことに気付きました(ただし、「in」はJavaScriptの予約語です)。
Nashornはエラーを発生させます。
Nashornはインスタンスの静的メソッドを呼び出すことができません! Rhinoはこれを行ったため、RhinoをJava 8にバックポートする必要がありました(以下に要約を示します: http://andreas.haufler.info/2015/04/using-rhino- with-Java-8.html )
Java8のNashornはASTをサポートしていません。したがって、RhinoのJavaメカニズムを使用してJSソースツリーを検査するコードASTコードがある場合は、 Nashornを使用するコード。
このAPIについて話している https://mozilla.github.io/rhino/javadoc/org/mozilla/javascript/ast/AstNode.html
Java9のNashornは、ASTをサポートしています。