Nashorn

Legacy

Nashorn появился в JDK 8, был объявлен устаревшим в JDK 11 и удалён из JDK начиная с 15. Наличие javax.script не означает, что в runtime установлен JavaScript engine.

Nashorn исполнял JavaScript внутри JVM, компилировал его в bytecode и позволял взаимодействовать с Java-объектами. Это было удобно для встроенных правил и скриптов, но создавало большую поверхность доступа к приложению.

ScriptEngine engine = new ScriptEngineManager()
        .getEngineByName("nashorn");
 
if (engine == null) {
    throw new IllegalStateException("Nashorn отсутствует в этой JVM");
}
 
Object result = engine.eval("40 + 2");

Этот пример нужен для чтения legacy-кода, а не как рекомендация для нового проекта.

Что делать сейчас

  • если скрипты не обязательны — выразить правила типизированным Java-кодом;
  • если нужен JS в процессе — выбрать и явно подключить поддерживаемый движок, например GraalJS;
  • если код недоверенный — предпочесть отдельный изолированный процесс/сервис;
  • ограничить время, память, host access и набор передаваемых объектов.

Один ScriptEngine не следует считать потокобезопасным без гарантии конкретной реализации. Компилируемый скрипт можно кэшировать, но его контекст и изменяемые bindings требуют отдельного решения.

Ошибки

  • ожидать Nashorn на новой JVM без зависимости;
  • давать пользовательскому скрипту неограниченный доступ к Java API;
  • выполнять скрипт без timeout;
  • смешивать бизнес-контракт с деталями конкретного engine.

На собеседовании

Есть ли Nashorn в современном JDK? В составе JDK 15+ — нет.

Почему getEngineByName может вернуть null? Подходящий provider не установлен.

Главный риск встроенных скриптов? Неконтролируемый доступ к ресурсам процесса и отсутствие лимитов.

Связано: Нововведения Java 8, Компилируемые и интерпретируемые языки.