2014-03-19 18 views
25

Ich habe ein Java 7-Projekt, das viel Javascript zum Scripting verschiedener Funktionen verwendet. Bisher habe ich Rhino als Skript-Engine verwendet. Ich würde jetzt gerne nach Java 8 ziehen, was auch bedeutet, dass ich Rhino durch Nashorn ersetzen werde.Wechsel von Rhino nach Nashorn

Wie kompatibel ist Nashorn zu Rhino? Kann ich es als Drop-In-Ersatz verwenden, oder kann ich erwarten, dass einige meiner Skripts nicht mehr funktionieren und auf die neue Engine portiert werden müssen? Gibt es einige gebräuchliche Rhino-Funktionen, die von Nashorn nicht unterstützt werden?

+1

Nein. Es ist ein bisschen gefährlich. Ich stieß auf diese: http://stackoverflow.com/questions/28152990/coercion-of-enums-in-nashorn-works-differently-than-in-rhino – MKK

Antwort

18

Ein Problem ist, dass Nashorn nicht mehr durch Standard-Import ganze Java-Pakete in den globalen Bereich von importPackage(com.organization.project.package);

Verwendung Es gibt jedoch eine einfache Abhilfe: Durch diese Zeile in Ihrem Skript hinzufügen, können Sie ermöglichen die altes Verhalten von Rhino:

load("nashorn:mozilla_compat.js"); 

Ein weiteres Problem, das ich in lief ist, dass bestimmte Art-Konvertierungen, wenn Daten zwischen Java und Javascript-Arbeit anders übergeben. Beispielsweise kann das Objekt, das beim Übergeben eines JavaScript-Arrays an Java eintrifft, nicht mehr an List übergeben werden, aber es kann in eine Map<String, Object> umgewandelt werden. Als Abhilfe können Sie den Javascript-Array auf eine Java-Liste in dem Javascript-Code umwandeln können mit Java.to(array, Java.type("java.util.List"))

+5

Nach [diesem Artikel] (http: // www. oracle.com/technetwork/articles/java/jf14-nashorn-2126515.html), die Verwendung von mozilla_compat.js und importClass wird abgeraten. Verwenden Sie 'var scope = new JavaImporter (com.x.y)' und dann 'scope.z' (wobei z im Paket' com.x.y' steht). Die automatische Konvertierung von einem JS-Array in eine Java-Liste funktioniert für mich. – ComFreek

9

Nashorn nicht eine innere Klasse zugreifen kann, wenn die innere Klasse privat deklariert ist, die Rhino der Lage war, zu tun:

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); 
     } 
    } 
} 

Unter Java8 wirft dieser Code folgende Ausnahme:

javax.script.ScriptException: TypeError: [email protected] 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) 
+0

Sie können nur auf öffentliche Methoden zugreifen. Wenn Sie zur öffentlichen Klasse Inner wechseln, wird es funktionieren. – wickund

+3

Ja, ich weiß. Aber das ist eine Art von Inkompatibilität. IMHO –

+2

Es geht um Sicherheit, die Rhino fehlt. – wickund

3

ich bemerkte, dass Rhino nicht ein Problem mit einer Funktion namens 'in()' (obwohl 'in' ist ein reserviertes JavaScript-Schlüsselwort) hat.
Nashorn jedoch einen Fehler melden.

9

Zur Verwendung der importClass Methode auf JDK 8 wir den folgenden Befehl hinzufügen müssen:

load("nashorn:mozilla_compat.js"); 

Diese Änderung wirkt sich jedoch auf die Ausführung in JDK 7 aus (JDK bietet keine Unterstützung für die load-Methode).

die Kompatibilität für beide SDKs zu erhalten, löste ich dieses Problem Hinzufügen von try/catch-Klausel:

try{ 
    load("nashorn:mozilla_compat.js"); 
}catch(e){ 
} 
-1

Ein Merkmal, das in Rhino und nicht nashorn: statische Mitglieder durch Instanzen auszusetzen.

Von http://nashorn-dev.openjdk.java.narkive.com/n0jtdHc9/bug-report-can-t-call-static-methods-on-a-java-class-instance. "

Meine Überzeugung ist, dass aussetzt statische Mitglieder durch Instanzen ist ein schlampig Maischen zusammen von sonst getrennten Namensräumen, daher wählte ich es nicht aktivieren

I denke, das ist zutiefst falsch.Solange wir zwei verschiedene Konstrukte verwenden müssen, um auf dasselbe Java-Objekt zuzugreifen und Paketdeklarationen unnötigerweise in Javascript zu verwenden, wird es schwieriger, Code zu lesen und zu schreiben, weil die kognitive Belastung zunimmt. Ich bleibe lieber bei Rhino.

Ich habe noch keinen Workaround für diesen offensichtlichen "Design-Bug" gefunden.

0

Nashorn auf Java8 unterstützt AST nicht. Wenn Sie also Java-Code haben, der den JS-Quellbaum mit dem AST-Mechanismus von Rhino inspiziert, müssen Sie ihn möglicherweise neu schreiben (vielleicht mit Regex), sobald Sie Ihren Code zur Verwendung von Nashorn portiert haben.

Ich spreche über diese API https://mozilla.github.io/rhino/javadoc/org/mozilla/javascript/ast/AstNode.html

Nashorn auf Java9 obwohl AST unterstützt.