原文はこちら。
The original entry was written by Oleg Šelajev (Developer advocate for GraalVM at Oracle Labs).
https://medium.com/graalvm/java-on-truffle-going-fully-metacircular-215531e3f840
これまでGraalVMでは、Javaプログラムを実行する方法として、GraalVM JITコンパイラとJava HotSpot VMを使用する方法と、GraalVM Native Imageを使用してネイティブ実行ファイルにコンパイルする方法の2つの方法を提供してきました。
本日は、GraalVM上でJavaを実行するための新しい方法を発表します。GraalVM 21.0では、espresso
という名前の新しいインストール可能なコンポーネントが導入されています。これはJavaで書かれたJVM実装を提供するものです。

Espressoにより、Truffleフレームワークを使ってJavaコードを実行することが可能になり、JavaをGraalVMでサポートされている他の言語のレベルに引き上げることができます。
Try it out
Java on Truffleを試すのは非常に簡単です。gu
コマンドでベースのGraalVMディストリビューションにインストール可能なコンポーネントとして利用できます。
gu install espresso
gu install -L espresso-installable.jar # if downloaded manually
インストール後、Java on Truffleでお気に入りのアプリを実行するには、-truffle
をjavaコマンドに渡せばOKです。
java -truffle -jar myApp.jar
Download Java on Truffleをダウンロードし、試してください。いくつかのアプリの例とともにJava on Truffleの特定の機能を説明する説明書をつけています。
Running Demo Applications
https://www.graalvm.org/reference-manual/java-on-truffle/demos/
なお、現在の素のJava on Truffleのパフォーマンスは、近い将来に可能になる予定のものを示してはいないことに注意してください。ピーク・パフォーマンスは、通常の JIT モードで同じコードを実行するよりも数倍低くなります。ウォームアップもまだ最適化されていません。この初期リリースでは、機能性、互換性、およびJava on Truffleのオープン・ソース化をより広いコミュニティが利用できるようにすることに完全に焦点を当てました。
ウォームアップとピーク時の両パフォーマンスが、今後出てくる21.xリリースのそれぞれで急速に向上することをご期待ください。
ではJava on Truffleの詳細を見ていきましょう。Java on Truffleが役立ついくつかの注目すべきユースケースを探り、より大きなGraalVMとJavaのエコシステムの中にプロジェクトを配置してみましょう。
Java on Truffle
Java on TruffleはTruffle言語実装フレームワークを使って実装されたJVMで、Java仮想マシンの全てのコアコンポーネントを提供します。
- バイトコード・インタプリタ
- バイトコード検証器
- シングルパス クラスファイル パーサー
- シンプルオブジェクトモデル
- JavaによるJava Native Interface (JNI) 実装
- Javaによる仮想マシン実装
- Java Debug Wire Protocol (JDWP)
この実装の非常に重要な詳細は、Javaで実装されているということです。Java on TruffleはJava on Javaなのです。自己ホスティングは、Java仮想マシン研究開発の至高の目標です。
Java on Truffleができること、それは、Javaプログラムの実行です。もちろん、他のJVM言語で書かれたプログラムもです。上記のリストからわかるように、デバッグ・プロトコルもサポートしているので、これを使ってJavaアプリケーションをデバッグすることもできます。
Java on TruffleはJava 8、Java 11ベースの両GraalVMで利用できますので、技術的にはお気に入りのJVMの代替として使用できます。Java on Truffleは現在実験的なものであり、まだそれほど高速ではありませんので、本番運用ワークロードには現時点ではお勧めできません。とはいえ、Java on Truffleでアプリケーションを実行することで得られるものを探ってみましょう。
Java on Java
先ほど述べたように、Java on Truffleは Javaで実装されています。これは仮想マシンの実装なので、実際にJavaコードを実行するためには、クラスライブラリやネイティブ・ライブラリ、、JDKが提供するメソッドにアクセスする必要があります。Java on Truffleは、GraalVMディストリビューションの JARとネイティブ・ライブラリを再利用します。
Javaで実装され、Javaが実行できるということにより、Java on TruffleはJavaがJavaを実行できるという、非常に興味深い特性を備えています。実際、Java on Truffle はメタサーキュラーVM(Metacircular VM)であるため、数レベルの深さで実行することができます(毎回遅くなりますが)。
Javaプログラムであることにより、数多くのアドバンテージがあります。その一つがNative Imageを使ってネイティブ実行形式にコンパイルできる点で、後ほどこの興味深いユースケースを探っていきます。
もう一つのアドバンテージは、Java開発者にとってコードが素晴らしく、親しみやすく、理解しやすいということです。GitHubリポジトリでソースコードを見てください。いつも使っているツールが対応していて、お使いのIDEがサポートしているため、他のJavaの依存関係を調べる場合と同じ方法でコードベースを調査できます。この透明性や親しみやすさにより、Java on Truffleは効率的により良いものに急速に変化していくはずです。
Embedding 11 in 8
Java on Truffleは実際のJVMであり、Javaプログラムでもあります。つまり別のJavaプログラム内で実行できるということです。これにより、アプリケーション内の異なるコンポーネントをコンパートメント化するという、非常に興味深い道が開かれます。例えば、Java on TruffleをJDK11ディストリビューションに向けると、Java 11を実行できますし、Java 8にアクセスする場合、Java 8になります。両方のディストリビューションが利用可能な場合、Java 8アプリケーションのコンテキストでJava on Truffleを実行し、それ(Java 8アプリケーションのコンテキストで実行しているJava on Truffle)を使ってJava 11バイトコードを実行できます。Java 8 でしか利用できないライブラリがある場合は、より新しいベースのJDKに移行しても、相互運用性を確立するようプログラム的に手を入れれば、同じJavaプロセス内で互換性のあるJDK 8で特定のライブラリを引き続き実行できます。
Mixing AOT and JIT
Java on Truffle、Truffle、GraalVMコンパイラ、およびJava on Truffleを効率的に実行するために必要なその他のコンポーネントはすべてJavaで記述されているため、Java on Truffle を実行するためのインフラストラクチャを使用してネイティブイメージの実行ファイルをビルドできます。
これはつまり、Javaアプリケーションを使ってJVMをビルドしてJavaアプリケーションに入れ込み、JVM上もしくはネイティブイメージとしてそのアプリケ-ションを実行できる、ということです。注意が必要です 後者の場合、Java on Truffleは、任意のJavaコードを実際に実行でき、そのJavaコードはビルド時に必ずしも知っておく必要がない点に注意してください。
その通り、Java on Truffleは、JITコンパイラとダイナミックJavaランタイムをAOTコンパイルされたバイナリに持ちこむことができます。

このコンセプトを説明するためのサンプルアプリケーションを用意しました。フロントエンドのCLIアプリとバックエンドの計算エンジンの2つの別々の部分からなる通常のJShellアプリで、バックエンドの計算エンジンをJava on Truffleの実装で置き換えたJShellの実装例です。
実際には、元の実装からクラスをロードするだけで、すべてのクラスを非常にきれいに再利用しています。つまり、サンプル・アプリケーションのオリジナルの部分は、ホストのJava部分とアプリのJava on Truffle部分を接続するglue(接着剤)コードです。
このサンプルをネイティブ実行形式にコンパイルできます。ネイティブ実行形式のパフォーマンス特性ゆえに、生成されたバイナリは通常のJShellよりも高速に起動し、それでいて投げ込んだJavaコードを実行できるのです。
以下はJava on Truffleで実装されたJShellからロード、起動したテトリスゲームのスクリーンショットです。

Mixing AOTとJITの組み合わせは、ネイティブイメージのパフォーマンス向上を活用できないアプリケーションにとって魅力的なオプションです。なぜなら、そうしたアプリケーションの機能は、Native Imageで簡単には動作しない動的コードに依存しているからです。
Advanced class redefinition
Java on TruffleがHotSpotよりも強力である、もう一つのクールな機能は、強化されたホット・スワップ機能です。これはデバッグ・セッション中に実行時にクラスを変更するというものです。
GraalVM 21.0では、以下の変更がサポートされています。
- メソッドの追加と削除
- コンストラクタの追加と削除
- インターフェースからのメソッドの追加と削除
- メソッドのアクセス修飾子の変更
- コンストラクタのアクセス修飾子の変更
- ラムダへの変更
- 新しい匿名内部クラス(inner class)の追加
- 匿名内部クラス(inner class)の削除
ホットスワップをさらに強力にするのは、クラスのフィールドに変更を加える機能です。現在作業中で、将来のリリースで追加される予定です。

セットアップはHotSpotの場合と同じです。デバッガを起動し、コードを変更し、クラスを再コンパイルして、IDEデバッガで「クラスのリロード」を呼び出します。すると変更されたクラスを次回使用する際に新しいコードが実行された状態でプログラムを再開します。
GraalVM ecosystem support
Java on Truffleは、GraalVM言語がTruffleフレームワークから得る開発者ツールのサポートからすぐに恩恵を受けることができます。
例えば、java -truffle --cpusampler
をつけてアプリケーションを実行でき、サンプリングプロファイラをコードで実行できます。トレースプロファイラやメモリトレーサーを有効にして、コードのどの部分が他の部分に比べてメモリプレッシャーをより多く生成しているのかを知ることができます。
エコシステムのもう 1 つの側面は、サポート対象の言語です。Java on Truffleを使うと、様々なコンポーネントが異なる言語で書かれている多言語(polyglot)プログラムを作成できます。別の言語で記述されたコードのロードや言語間のオブジェクトのインポートやエクスポート方法などの詳細は、この記事の範囲よりやや複雑ですが、詳細は以下のドキュメントに記載があります。
Interoperability with Truffle Languages
https://www.graalvm.org/reference-manual/java-on-truffle/interoperability
Next steps
GraalVM 21.0は、Java on Truffleの初期リリースです。現在は実験的なコンポーネントであり、今後のリリースで大幅な改善が予定されています。
javaagent
のサポートから、他の言語との相互運用プロトコルのより良い実装、パフォーマンスの大幅な改善など、改善すべき点はたくさんあります。
今後これらの改善やその他の改善に取り組んでいきますが、現在のバージョンのフィードバック、機能要求、可能性のあるユースケース、発見された問題点、欠点など、あらゆるフィードバックを是非お聞かせください。フィードバックはSlack、GitHub、Twitterでお寄せいただけます。
Slack invitation
https://www.graalvm.org/slack-invitation
GitHub Issues
https://github.com/oracle/graal
Twitter
https://twitter.com/graalvm
まずは以下のドキュメントから始めてください。
Java on Truffle
https://www.graalvm.org/java-on-truffle/
Java on Truffleは、Javaコードを実行するための新しい非常にエキサイティングな方法です。ご覧いただき、その可能性を検討くださいませ。