Nashorn:JavaScriptはJava8で素晴らしいものになりました

「nass-horn」と発音されるNashornは、ドイツ語で「サイ」を意味し、第二次世界大戦で使用されたドイツの駆逐戦車の動物名の1つです。これは、Java8で導入された古い低速のRhinoJavaScriptエンジンの代替品の名前でもあります。RhinoとNashornはどちらも、Java仮想マシン(JVM)で実行するように記述されたJavaScript言語の実装です。

義務的な暴言:JavaScriptの名前の一部にJavaが含まれている場合がありますが、2つの言語は、精神とデザイン、および実装が大きく異なります。それでも、JavaScriptインタープリターを実装する1つの方法は、JavaScriptをJavaバイトコードにコンパイルすることです。これは、RhinoとNashornが行うように設計されたものです。

あなたはおそらくJavaScriptをWebブラウザのスクリプトの観点から考えているでしょう、そしてあなたはほとんどの部分で正しいでしょう。サーバーにも使用されます。たとえば、Node.jsは、GoogleChromeのV8JavaScriptエンジンに基づいて高速で軽量なサーバーを構築するために使用されます。 WebブラウザのJavaScriptエンジンは、HTMLドキュメントオブジェクトモデル(DOM)にアクセスでき、DOMを介してHTML要素を操作できます。 Webブラウザが異なればDOMとJavaScriptエンジンも異なるため、jQueryなどのフレームワークは実装の詳細をプログラマーから隠そうとします。

Nashornとその前のRhinoは、ブラウザのDOMを明示的にサポートしていません。これらはJVMに実装され、通常、Javaアプリケーションのエンドユーザースクリプト用に呼び出されます。NashornとRhinoは、Javaプログラムに組み込んで、コマンドラインシェルとして使用できます。もちろん、JavaScriptからJavaをスクリプト化するときに必要な追加の魔法は、2つの言語間のデータとタイプの不一致をブリッジすることです。

Rhinoの問題

Rhinoの開発は、不運な「Javagator」プロジェクトのために1997年にNetscapeで開始され、1998年にMozilla.orgにリリースされました。その後、Sunなどにライセンス供与されました。正直なところ、インターネットの開発が進むにつれて、1998年はジュラ紀の時代でもあるかもしれません-16年後、Rhinoは明らかにその時代を示しました。Nashornの主な開発者であるOracleのJimLaskeyによると、

これはすべて真実だと確信していますが、うんざりした開発者および開発マネージャーとして、最後の文は非常に面白いと思います。結局のところ、主要な書き直しは決して楽しいものではありません。ゼロから始めるのはいつも楽しいです。

ナソーンの目標

ラスキーはナソーンの目標を次のように説明しました。

  • Nashornは、ECMAScript-262 Edition 5.1言語仕様に基づいており、ECMAScript-262コンプライアンステストに合格する必要があります。
  • Nashornはjavax.script(JSR 223)APIをサポートします。
  • JavaScriptからJavaコードを呼び出すためのサポートと、JavaがJavaScriptコードを呼び出すためのサポートが提供されます。これには、JavaBeansへの直接マッピングが含まれます。
  • Nashornはjjs、「シバン」スクリプト(ヒアドキュメント)のJavaScriptコードを評価し、文字列を編集するための新しいコマンドラインツールを定義します。
  • Nashornアプリケーションのパフォーマンスとメモリ使用量は、Rhinoよりも大幅に優れているはずです。
  • Nashornは、追加のセキュリティリスクを公開しません。
  • 提供されたライブラリは、ローカリゼーションの下で正しく機能するはずです。
  • エラーメッセージとドキュメントは国際化されます。

ラスキーはまた、いくつかの「非目標」でプロジェクトの範囲を明示的に制限しました。

  • Nashornは、ECMAScript-262 Edition5.1のみをサポートします。Edition 6の機能や、他のJavaScript実装によって提供される非標準機能はサポートされません。
  • NashornにはブラウザプラグインAPIは含まれません。
  • Nashornには、DOM / CSSまたは関連するライブラリ(jQuery、Prototype、Dojoなど)のサポートは含まれません。
  • Nashornには、直接デバッグのサポートは含まれません。

では、ECMAScript-262 Edition 5.1に基づくとはどういう意味ですか?ここでの差別化要因は、Rhinoが古い、機能の少ないEdition 3に基づいていることです。javax.script(JSR223)APIは、JavaからJavaScriptにコールバックするためのものです。

Nashornでのデバッグサポートの欠如は、独自のJavaScriptデバッガーを備えたRhinoから一歩後退したものです。ただし、少なくとも2つの一般的なIDEで、この意図的な省略の回避策を見つけることができます。

Nashornコマンドラインツール:jjsとjrunscriptのインストール

Nashornのコマンドラインツールについて読んだ後jjs、私はiMacでシェルを試してみたいと思っていましたが、Java 8をインストールした後、bashシェルで使用できませんでした。ドキュメントと実装が完全に同期していなかったことが判明しました。

インストールが成功したことはわかっていました。

 >java -version java version "1.8.0" Java(TM) SE Runtime Environment (build 1.8.0-b132) Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode) 

しかし、実行jjsは戻りました-bash: jjs: command not found。少し突っ込んで、/usr/bin/ディレクトリに移動しました。

 >which java /usr/bin/java 

そこで、追加の起動スクリプトを実行するjrunscriptバリアントであるjjsことが判明した、と呼ばれるものを見つけました。それは私を満足させるはずでしたが、文書化jjsされたツールが/usr/bin/残りのJava8ランタイムにインストールされなかった理由について私は戸惑いました。少し調べてみると、JavaVirtualMachinesJava 8のインストールを調べることになりました。Macではjjs/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/bin/またはを探してください/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/bin/

jjsMacまたはLinuxでのスクリプト作成に必要な場合は、後者のディレクトリでエイリアスを定義し、シェル構成に追加できます。PCでは、正しいjre/bin/ディレクトリをに追加できますPATH。Java 8の起動からの彼のビデオで、Jim Laskeyjjs/usr/bin/ディレクトリにコピーすることを提案してjjsいますが、それを実行すると、実行時にJREが正しく見つからないことがわかりました。

JavaScriptスクリプトの実行

JavaScriptスクリプトを実行するための2つのコマンドラインツールはなぜですか?開発チームが何を考えていたのか完全にはわかりませんが、そうjjsjrunscriptはない機能がjrunscriptあり、初期化ファイルがあります。以下は、いくつかの簡単な例jjsjrunscript使用法です。

 $ jrunscript nashorn> alert("hello, "); script error: ReferenceError: "alert" is not defined in  at line number 1 

alert()はブラウザ/ DOM機能であるため、これは機能しません。D'oh!しかし、Rhinoで機能することを誓ったかもしれません。

 nashorn> print("Hello, "); Hello,  

print()はJavaScriptのコア関数であるため、これは機能します。

 nashorn> var a = 1; nashorn> var b = "1"; nashorn> print (a+b); 11 nashorn> print(a+a); 2 nashorn> quit(); $ 

つまり、ここにはJavaScript用の基本的なREPL(read-execute-print-loopコマンドライン)環境があります。の答えに驚いた場合はa+b、次のことを検討してください。

 nashorn> print (typeof(a+b)); string 

これは、JavaScriptの「+」演算子の緩い型付けとオーバーロードの魅力的な副作用です。これは、バグではなく、JavaScript仕様に従った正しい動作です。

Nashorn supports the "#" character as a leading line comment marker, so jjs and jrunscript can be used in executable "shebang" scripts written in JavaScript. On a Mac or Linux, you'll have to mark the JavaScript file as executable with the chmod utility to make it runnable.

You'll find a scripting mode in jjs that jrunscript seems to lack. In scripting mode, expressions inside back-ticks are passed to the outer shell for evaluation:

 $ jjs -scripting jjs> print ('ls'); Applications Applications (Parallels) Creative Cloud Files Desktop ... work jjs>

Scripting mode also enables an extension for "heredocs," which are basically multiline strings in a format familiar to Perl and Ruby programmers.

By the way, the arrow keys on the Mac keyboard don't work properly for line editing in the jjs shell. But there is a hack for that: You can brew install rlwrap and use that as part of your alias for jjs in your .bashrc or .zshrc file.

Calling JavaScript from Java

To call Nashorn JavaScript from a Java 8 program, you basically need to make a new ScriptEngineManager instance and use that ScriptEngineManager to load the Nashorn script engine by name. (See this Stack Overflow question for a pithy summary of loading and debugging Nashorn.)

Finally, you can pass the Nashorn engine a file or a string to evaluate:

 import javax.script.Invocable; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; ... try { ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName("nashorn"); engine.eval("load(\"" + "src" + "/" + "javascript_sample" + "/" + "test1.js" + "\");"); } catch (Exception ex) { //... } ... try { ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName("nashorn"); engine.eval("function hi(){\nvar a = 'PROSPER'.toLowerCase(); \nmiddle(); \nprint('Live long and' + a)}\n function middle(){\n var b = 1; for(var i=0, max = 5; i
    

Note that scripts can always generate ScriptException errors, so you need to catch them.

Calling Java from JavaScript

Calling Java from Nashorn is about as easy as it can be, since the Java 8 class libraries are built into Nashorn:

 print(java.lang.System.currentTimeMillis()); var file = new java.io.File("sample.js"); print(file.getAbsolutePath()); print(file.absolutePath); 

Note that Nashorn does not import the java package by default, because references to String or Object conflict with the corresponding types in JavaScript. Hence, a Java string is java.lang.String, not String.

Nashorn and JavaFX

If you invoke jjs with the -fx switch, it will allow you to use visual JavaFX classes in your Nashorn applications. For instance, the following example from the Oracle documentation displays a JavaFX button:

 var Button = javafx.scene.control.Button; var StackPane = javafx.scene.layout.StackPane; var Scene = javafx.scene.Scene; function start(primaryStage) { primaryStage.title = "Hello World!"; var button = new Button(); button.text = "Say 'Hello World'"; button.onAction = function() print("Hello World!"); var root = new StackPane(); root.children.add(button); primaryStage.scene = new Scene(root, 300, 250); primaryStage.show(); } 

Debugging Nashorn

I mentioned earlier that Nashorn doesn't include a debugger of its own. Fortunately, both NetBeans 8 and IntelliJ IDEA 13.1 support debugging Nashorn JavaScript. The Stack Overflow question I mentioned earlier includes a useful NetBeans 8 project that you can use as a sample. You'll find that simply using the debug item from the pop-up menu on JavaScript files will allow you to debug the Nashorn code.

In IntelliJ IDEA 13, you can set breakpoints in the Java and Nashorn JavaScript files using the same shortcut key (Com/Ctrl-F8). When you hit a JavaScript breakpoint, you get all the usual debugging information.

Nashorn was designed to be a better, faster replacement for the old Rhino engine, and by most measures it succeeds. It has some minor warts that I hope will be corrected in future updates, but for now there are reasonable hacks to let you use Nashorn effectively in your projects.