Подтвердить что ты не робот

Переход от Носорога до Нашорна

У меня есть проект Java 7, который много использует Javascript для написания различных функций. До сих пор я использовал Rhino как движок script. Теперь я хотел бы перейти на Java 8, что также означает, что я заменил Rhino на Nashorn.

Насколько совместим Нашорн с Носорогом? Могу ли я использовать его в качестве замены для замены, или я могу ожидать, что некоторые из моих скриптов больше не будут работать, и их нужно будет портировать на новый движок? Существуют ли обычно используемые функции Rhino, которые не поддерживаются Nashorn?

4b9b3361

Ответ 1

Одна из проблем заключается в том, что Nashorn уже не может по умолчанию импортировать целые пакеты Java в глобальную область с помощью importPackage(com.organization.project.package);

Существует, однако, простой способ: добавив эту строку в свой script, вы можете включить старое поведение Rhino:

load("nashorn:mozilla_compat.js");

Другая проблема, с которой я столкнулся, заключается в том, что определенные преобразования типов при передаче данных между java и javascript работают по-другому. Например, объект, который появляется при передаче массива Javascript на Java, больше не может быть перенесен в List, но его можно отнести к Map<String, Object>. В качестве обходного пути вы можете преобразовать массив Javascript в список Java в коде Javascript, используя Java.to(array, Java.type("java.util.List"))

Ответ 2

Чтобы использовать метод importClass на JDK 8, нам нужно добавить следующую команду:

load("nashorn:mozilla_compat.js");

Однако это изменение влияет на выполнение на JDK 7 (JDK не поддерживает метод загрузки).

Чтобы поддерживать совместимость для обоих SDK, я решил эту проблему, добавив предложение try/catch:

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

Ответ 3

Nashorn не может получить доступ к внутреннему классу, когда этот внутренний класс объявлен частным, что 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: [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)

Ответ 4

Я заметил, что у Rhino не было проблемы с функцией "in()" (хотя "in" - это зарезервированное ключевое слово JavaScript).
Ношорн, однако, выдает ошибку.

Ответ 5

Nashorn не может вызывать статические методы для экземпляров! Rhino сделал это, поэтому нам пришлось заложить Rhino на Java 8 (здесь короткое резюме: http://andreas.haufler.info/2015/04/using-rhino-with-java-8.html)

Ответ 6

Nashorn на Java8 не поддерживает АСТ. Поэтому, если у вас есть Java-код, который проверяет исходное дерево JS с использованием механизма Rhino AST, вам, возможно, придется переписать его (возможно, с помощью регулярного выражения), как только вы портируете код для использования Nashorn.

Я говорю об этом API https://mozilla.github.io/rhino/javadoc/org/mozilla/javascript/ast/AstNode.html

Nashorn на Java9 поддерживает AST, хотя.

Ответ 7

я использовал Mozilla Rhino в java6, и я переносил свой проект в java8 Nashorn и хотел использовать rhino, я добавил требуемый оператор в свой код загрузки java ("nashorn: mozilla_compat.js");

Но проблема, с которой я столкнулся при импорте меток классов. Мне нужно импортировать пару классов из моего файла JAR, который я использую в файле JS. importClass работает нормально для класса пакета java/javax, как. importClass (java.util.HashSet);

Но я не могу сделать импорт метки класса из другого файла класса jar файла, который присутствует в пути к классам. например importClass (Packages.mypack.ABC);

Тот же код работал нормально, когда я использовал java6/Rhino, Appriciate, если кто-то может мне помочь с этим.

Ответ 8

Одна функция, которая находится в Rhino, а не в Nashorn: отображение статических элементов через экземпляры.

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

Моя убежденность в том, что разоблачение статических элементов через экземпляры - это небрежное затирание в противном случае отдельных пространств имен, следовательно, я решил не включать его.

Я думаю, что это глубоко неправильно. До тех пор, пока мы должны использовать две разные конструкции для доступа к одному и тому же объекту java и без необходимости использовать объявления в javascript, код становится сложнее читать и писать, потому что увеличивается когнитивная нагрузка. Я скорее буду придерживаться Rhino.

Я еще не нашел обходного пути для этой очевидной "дизайнерской ошибки".