Static Javaは、静的コンパイルされたネイティブ実行コードを生成することにより、起動の高速化に加えて、ディスク上と、メタデータによるオーバーヘッドの少ない実行時との両方で、小さなフットプリントの実現を目指している。InfoQは今回、Static Javaの本格的普及に向けた道程を理解すべく、コントリビュータとして開発に長く携わっている、Red HatプリンシパルソフトウェアエンジニアのDan Heidinga氏に話を聞いた。
氏のStatic Javaとの関わりは、クラウド関連の新たなプラクティスが促すエコシステム改革に対応するように、Javaを進化させる必要がある、という認識から始まっている。OpenJDKのProject CRacとOpen J9のCRiUの両方でCRiU(ユーザ空間でのチェックポイント/リストア)に関わりながら、OpenJ9 JVMやJava Lambdaへのコントリビューション、Method HandlesのJavaへの導入、そして現在はProject Valhallaにも関与する氏は現在、Static Javaに向かう旅の最前列に席を持っている。
InfoQ: こんにちは、Dan。読者の質問に答えるために、時間を取ってくれてありがとう。簡単な自己紹介と、日々の役割、Static Javaとの関係について説明してもらえますか?
Dan Heidinga: 私は古くからのJVM開発者で、Javaユーザです。日々の業務では、Hotspot JVM(OpenJ9のHotspot JVM開発のプロジェクトリーダでもあります)やqbiccプロジェクトに従事しています。qbiccプロジェクトは、Javaプログラム用の静的コンパイラを開発する実験的プロジェクトです。Static Javaへのさまざまなアプローチを試すプレイグラウンドとして機能することで、OpenJDKのProject Leydenのための完全な設計空間の探索に寄与することを目指しています。
CRiU(ユーザ空間でのチェックポイント/リストア)の調査にも、OpenJDKのProject CRacとOpenJ9のCRiUの両方で積極的に参加しています。チェックポイント/リストアとStatic Javaのニーズには、オーバーラップする部分がたくさんあるのです。
InfoQ: Static Javaのメリットは何で、最適なユースケースはどのようなものでしょうか?
Heidinga: Static Javaは、静的コンパイルされたネイティブ実行コードを生成することで、起動の高速化に加えて、ディスク上と、メタデータによるオーバーヘッドの少ない実行時との両方で、小さなフットプリントの実現を目指すものです。活用できそうなシナリオはたくさんありますが、特に有望なのはマイクロサービス、CLIアプリケーション、サーバレスデプロイメントなどですね。
Static Javaの提供する機能はそれほど多くありません。
- アプリケーションを構成するJavaコードのネイティブコンパイル。
- "閉じた世界"の実現による、追加的なクラスロードの防止。使用されないメソッドやフィールドを取り除くことでデッドコードを排除し、生成するバイナリを小さくします。
- ビルド時にアプリケーションの一部を初期化することで、さらなる最適化を可能にすると同時に、以降の起動時における冗長な処理を回避する機能。
最も大きなメリットは、単一でコンパクトな実行可能デプロイメントパッケージによる起動の高速化です。起動が速くなるのは、クラスのロードと検証、フィールドやメソッドを最初に使用する時の名前解決といった、Javaで動的に行われている処理を回避できるからです。ビルド時初期化を使用して、クラス初期化のような処理を実行時からビルド時に移動することも、起動の高速化に寄与しています。
実行時フットプリントの改善が最も明確に現れるのは、アプリケーションが必要とするヒープの少なさです。ヒープサイズを見れば、クラスのメタデータに必要なメモリ量の小さいことは一目瞭然です。
InfoQ: これまでのJavaの"動的VM"モデルからStatic Javaに移行する上で、開発者には何が必要なのでしょうか?
Heidinga: ガイドやツールが用意されてはいますが、アプリケーションを静的なものに変換する上で生じる課題に対処するために、ある程度の作業は必要であることは理解しておいてください。
Static Javaは、その名が示すとおり、通常のJavaよりも動的な部分が非常に少なくなっているので、リフレクションやMethodHandle、クラスのローディング、バイトコード生成、JVMTIエージェントといったJavaの動的機能を多用している場合には、問題が発生する可能性があります。これらの動的機能の実行時使用をサポートするために必要なコンフィギュレーションファイルを作るには、GraalVMのトレーシングエージェントから始めてみるとよいでしょう。動的機能が制限されることと、ビルド時に明示的にオプトインする必要があることは、Static Javaの要件のひとつなのです。
Static Javaを使用するフレームワーク(QuarkusやMicronautなど)を選んでおけば、採用時のハードルなしにそのメリットを活用することができます。
InfoQ: Static Javaは実運用でも使われているのでしょうか?
Heidinga: 実際に運用しているアーリーアダプタもいますが、信頼性や知識の習得を目的とする新分野のプロジェクトや、重要でないユースケースでの使用が大部分です。OpenJDKのProject Leydenがモデルを標準化することによって、採用が促進されるのではないか、と期待しています。現時点のStatic Javaは、作業をスムーズにしてくれるフレームワークを使わなければ、まだまだ導入が難しい状況なのです。
クラウドプラクティスが今後も業界内でシェアを広げ続けて、ユーザがクラウド展開のコストをもっと意識するようになれば、採用数は今後も増えると思います。ですが、Static Javaの要件に適応しないソフトウェアもたくさんありますから、採用ペースは上がらないでしょう(まあ、それでよいのですが!)。今は、Static Javaの持つ特性を必要としているユーザが、これらの機能がいかに重要であるかを理解し始めたところなのです。
メインストリームでの採用を本当に増やすには、Java自体がフェーズ変更(ビルド時と実行時、チェックポイントとリストア)を認識して、それらの持つ意味を伝えるツールを開発者に提供する必要があります。将来的にはそうなると思いますが、現在のOpenJDKプロジェクトのタイムフレームを考えると、1年以上先のことになりそうです。
クラウドへの移行が定常化し、起動時間の短縮とフットプリントの削減が求められる中で、Static Javaはその第一歩を踏み出したばかりなのだ、とHeidinga氏は言う。しかしProject Leydenの実施は、その採用を加速する可能性がある。いずれにしても今は試行段階だ、とする氏は、Red HatのディスティングイッシュトエンジニアであるAndrew Dinn氏の主導する実験を紹介している。Heidinga氏はまた、2020年に承認されたProject Leydenの進捗について、説明するのは難しいとしながらも、次のように述べている。
OpenJDKとその周辺のコミュニティでは、多くの調査や探求が行われています。これが近い将来、Project Leydenに集約されることを願っています。
Project CRaCなどいくつかのプロジェクトは、特に"Javaプログラミングモデルのさまざまなフェーズを公開する方法"において、Leydenの問題空間と重複する部分がある。さらにGraalVMコミュニティもSubstrateVMの改良を続けている。
Static Javaの採用では克服できないような問題に直面した場合や、既存の動的設計を変更したくない場合であっても、起動速度を向上する方法は存在する。例えば、Project CRaCなどCRiU関連の開発では、静的Javaと動的Javaの間に新たなポイントを見付けようとしている。