Nashorn完全ガイド:JDK8導入のJavaScriptエンジンが廃止された理由とGraalVMへの安全な移行手順
Nashorn とは
Nashorn(ナスホルン)は、Javaプラットフォーム上で動作するJavaScript実装(JavaScriptエンジン)です。Oracle / OpenJDKのプロジェクトとして開発され、主にJava 8(JDK 8、2014年公開)で導入されました。従来Javaで使われてきたRhino(MozillaのJavaScriptエンジン)の後継として性能向上とJVMとの親和性を目指して設計され、Javaアプリケーション内部からJavaScriptを実行・組み込みやすくする目的で提供されました。
名称の由来
「Nashorn」はドイツ語で「サイ(rhinoceros)」を意味します。これはRhino(rhinoceros)へのオマージュでありつつ、新しいエンジンであることを示す名称です。
歴史と経緯
- 2014年:JDK 8にNashornが導入され、標準のスクリプトエンジンとしてJavaプラットフォームに組み込まれました。これによりjavax.script(JSR 223)経由でJavaアプリケーションからJavaScriptを実行できるようになりました。
- 設計当初からJVMのパフォーマンス機能(特にinvokedynamicなどの動的言語対応機構)を活用することで、従来のエンジンより高速化を図っていました。
- その後のJavaの進化やJavaScript仕様(ECMAScript)の発展に伴い、Nashornは段階的に機能追加や改善が行われましたが、最新のECMAScript機能への追随が十分でない点やメンテナンスコストの問題が指摘されました。
- 2018年(JDK 11):Nashornは非推奨(deprecated)となりました(OpenJDKのJEPによる提案)。
- 2020年(JDK 15):OpenJDKからNashorn本体は削除されました(Remove)。以降、標準JDKには含まれません。
主な技術的特徴
- JVM上で動作するJava実装:Nashorn自体はJavaで実装され、JVMの上で動作するため、Javaのエコシステム(クラスやライブラリ)に直接アクセスできます。
- javax.script(JSR 223)準拠:ScriptEngine APIを通じてJavaコードからスクリプトの実行・値の受け渡しが行えます。
- invokedynamicの活用:JSR 292に基づくinvokedynamicやその他JVMの最適化機構を使うことで、実行性能の改善を図っています。
- Javaとの相互運用性:JavaScriptからJavaクラスを参照・利用できる機能(例えばJava.typeなど)を備え、スクリプト側から容易にJavaのオブジェクトを操作できます。
- ECMAScript互換性:主にECMAScript 5.1相当を目標にしており、ES6(ES2015)以降の機能については完全対応していない部分がありました。後続の仕様や最新のJS機能を必要とする場合は注意が必要です。
- コマンドラインツール:JDK 8ではjjsという対話型/スクリプト実行ツールが付属していました(JDKからの削除により現在は標準で利用できない環境もあります)。
基本的な使い方(例)
JavaプログラムからNashornを使う代表的な方法はScriptEngineを介するものです。JDK 8での基本的な例を示します。
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
Object result = engine.eval("var x = 10; var y = 20; x + y;");
System.out.println(result); // 30
また、スクリプトからJavaクラスを使う例:
// JavaScript側のコード(Nashorn)
var ArrayList = Java.type("java.util.ArrayList");
var list = new ArrayList();
list.add("foo");
list.add("bar");
list.size(); // 2
上記のように、JavaとJavaScript間でオブジェクトやメソッドをやり取りできます。ただし、これらのAPIやエンジン名("nashorn")はJDKのバージョンや環境によって使えない場合があります(JDK 15以降はデフォルトで含まれない)。
廃止・削除理由と現状の選択肢
Nashornが非推奨となり最終的にJDK本体から削除された理由はいくつかあります。主なものは以下です:
- ECMAScriptの急速な発展に追随するコスト:ES6以降の機能追加が頻繁で、完全追随するには大きなリソースが必要でした。
- コミュニティと利用状況:運用コストと比べてコミュニティでの維持・利用の割合が相対的に低かった点。
- 代替技術の台頭:より高度なパフォーマンスや最新のECMAScript互換性を提供するGraalVMのGraal.jsや、外部のNode.jsプロセスを活用する方法などが現実的な代替となった点。
そのため、現在の実務では以下のような選択肢が推奨されることが多いです:
- GraalVMのJavaScriptエンジン(Graal.js)への移行:多くの最新ECMAScript機能をサポートし、JVM上でのポリグロット実行も可能。
- Node.jsなど外部JavaScriptランタイムとプロセス間通信(プロセス連携やHTTP/IPC)でやり取りする方式。
- スクリプト実行が限定的であればRhinoや他のサードパーティ製スクリプトエンジンの利用。
移行時の注意点
- ECMAScript仕様差:Nashorn固有の拡張や振る舞い(Javaとの結合方法など)に依存しているコードは、そのままではGraal.jsやNodeで動かない可能性があります。テストとコード修正が必要です。
- API差分:ScriptEngine APIを介した呼び出しは移行先のAPI(GraalVMのPolyglot APIなど)と異なるため、呼び出し箇所の書き換えが必要になります。
- パフォーマンス特性:処理負荷や実行パターンによって最適解が変わります。単純なスクリプト埋め込みなら軽量な代替が良い場合、最新のJS仕様や高速性が重要ならGraalVMが有利です。
- ビルド・配布:JDKに同梱されていた環境から切り離す場合、実行環境に追加のライブラリやランタイム(GraalVMや外部のNode.js)が必要になることを考慮してください。
まとめ(いつ使うべきか)
NashornはかつてJavaとJavaScriptを密に結びつける便利なエンジンでしたが、現在はJDKに含まれないため新規開発での採用は慎重に検討する必要があります。既存のレガシーシステムでNashornに強く依存している場合は、段階的な移行(まずはテストと互換性チェック、次にGraalVM等への置換)を検討してください。新規プロジェクトであれば、最初からGraalVM/ Graal.jsやNode.js+プロセス連携といった選択肢を検討するほうが将来性・互換性の面で有利です。
参考文献
- OpenJDK: Nashorn プロジェクト
- Oracle Java SE 8 ドキュメント: Nashorn Guide
- JEP 335: Deprecate the Nashorn JavaScript Engine
- JEP 372: Remove the Nashorn JavaScript Engine
- GraalVM — 高性能ポリグロットランタイム(Graal.js を含む)
- Mozilla Rhino(参考:従来のJava向けJSエンジン)
- JSR 223: Scripting for the Java Platform
- JSR 292: Supporting Dynamically Typed Languages on the Java Platform(invokedynamic 関連)


