2015-08-16 1 views
2

J'étudie la possibilité de déplacer un énorme projet basé sur le rhino vers le nashorn. Ce projet a des milliers d'étendues (~ instances) exécutées dans un script compilé par rhino (de 10k + lignes de javascript).Nashorn, compilez une fois pour plusieurs portées, comme pour Rhino

Ce que je sais comment faire:

  • moteurs nashorn multiples me donner plusieurs champs/indépandent. Fonctionne mais comsumes waaaayyyyy trop de mémoire (1000 moteurs ...)
  • eval une chaîne sur un CompiledScript nashorn. Fonctionne aussi mais rend presque impossible de passer des objets/instances Java complexes à la fonction que je veux appeler.

Exemple de ce que je peux faire avec Rhino et que vous voulez être en mesure de le faire avec Nashorn:

String SOURCE = "var i = 0; function add(a) { i += a; return i; }"; 
System.out.println("=== RHINO ==="); 
Context cx = Context.enter(); 
cx.setOptimizationLevel(Context.FEATURE_STRICT_EVAL); // optimization level 9 

Script script = cx.compileString(SOURCE, "mySource", 1, null); // compile once 

Scriptable scope1 = cx.initStandardObjects(); // 1st re-use 
Scriptable scope2 = cx.initStandardObjects(); // 2nd re-use 

script.exec(cx, scope1); 
script.exec(cx, scope2); 

Function add1 = (Function) scope1.get("add", scope1); 
Function add2 = (Function) scope2.get("add", scope2); 

try { 
    Object r1 = add1.call(cx, scope1, scope1, new Object[]{6}); 
    System.out.println("result1=" + r1); // print 6 
    r1 = add1.call(cx, scope1, scope1, new Object[]{4}); 
    System.out.println("result1=" + r1); // print 10 
} catch (Exception ex) { 
    ex.printStackTrace(); 
} 

try { 
    Object r2 = add2.call(cx, scope2, scope2, new Object[]{9}); 
    System.out.println("result2=" + r2); // prints 9 
    r2 = add2.call(cx, scope2, scope2, new Object[]{3}); 
    System.out.println("result2=" + r2); // prints 12 
} catch (Exception ex) { 
    ex.printStackTrace(); 
} 

Context.exit(); 

Dans l'exemple ci-dessus, je compile une fois le script et utiliser des étendues multiples pour isoler mon autre exécution instances. Comment puis-je faire une telle chose avec Nashorn? Gardez à l'esprit que dans mon projet réel, je veux invoquer des fonctions beaucoup plus complexes qui prendraient des instances javascript ou java dans les paramètres.

Merci d'avance pour votre aide.

Répondre

0

Nashorn prend en charge la primitive loadWithNewGlobal (https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions#Nashornextensions-loadWithNewGlobal). Cette primitive vous permet de charger des scripts dans nouvelle portée globale - chacun ayant ses propres définitions pour "Objet", "Fonction", etc. Il semble que cela puisse vous aider dans votre cas d'utilisation. Il existe également une prise en charge de la méthode d'objet/propriété d'accès inter-scope. c'est-à-dire que vous pouvez passer et renvoyer des objets vers/depuis des scripts évalués dans des portées différentes - l'encapsulation/mise en miroir appropriée est prise en charge par Nashorn.