Oracle Labsは、Java 16用の試験的バイナリをフィーチャしたGraalVM 21.1をリリースした。今回の新リリースでは、ネイティブイメージでの複数ロケールのサポートといった新機能に加えて、パフォーマンスの向上も図られている。一方、従来バージョンのGraalVMインストールパッケージに元々含まれていたNode.jsはオプション扱いになり、マニュアルでのインストールが必要になった。
OpenJDKベースのGraalVM Community EditionバイナリはJava 8u292、11.0.11、16.0.1に、Oracle JDKベースのGraalVM Enterprise EditionバイナリはJava 8u291、11.0.1、16.0.1に、それぞれアップデートされている。いずれのエディションのJava 16サポートも、テスト用および評価用には使用可能だが、現在まだ開発中である。JDK16のネイティブイメージ生成に関しては、デフォルトのプロキシメソッドを使ってネイティブイメージを構築した時にエラー"unexpected method:proxyClassLookup
"が発生する場合があること、クラス内のラムダ式が実行時に初期化される時にエラー"jdk.vm.ci.common.JVMCIError: Unknown JvmConstant tag 17
が発生すること、JDK Flight Recorder(JFR)サポートが使用不可能であること、という3つの既知の問題がある。Visual VMなど他のツールのいくつかは、すでにJDK 16に対応している。AppleのM1チップにも対応するようになった。
新バージョンのVisual Studio Code (VS) Extensionでは、ユニットテスト結果の視覚化と、Javaコードのリファクタリングのサポートが提供されている。最初に導入されたGraalVM 19.2以来、Micronaut VS Code ExtensionやYAMLおよびDockerビルドのサポート、コンフィギュレーションファイルやJavaコードの支援といった、さまざまな機能が追加されてきた。
GraalVM 19.0リリースのnative-image
ユーティリティと同じく、Node.jsが、今回リリースからマニュアルインストールの必要なオプション機能となり、デフォルトで有効になることはなくなった。GraalVMのアップデートユーティリティであるgu
を使えば、コマンド"gu install nodejs
"でインストールできる。この変更の結果、Community Editionのダウンロードサイズは50MBほど小さくなった。JavaScriptランタイムについては、引き続きGraalVMインストールに含まれる。
GraalVM Community EditionのOpen JDK 8ベースMacOS用ビルドは、前回で提供が終了している。Linux AArch64ビルドは引き続き実験段階(experimental)だが、GraalVMコンパイラ、gu
ツール、Node.js、Native Image、いくつかの開発者ツールが新たに含まれるようになった。
コンパイラがさらに最適化されて、x86プロセッサのシーケンシャルな揮発性書き込み(volatile write)に関する不要なメモリバリアが排除された。コードのインライン化では、多数の揮発性書き込みがシーケンスに起きる場合がある。新たなコンパイラは、シーケンスの最後の書き込みを除くメモリバリアを削除するようになった。これにより、>ConcurrentHashMap.transfer()
のようなメソッドのパフォーマンスが向上する。
もうひとつの最適化は、ロードされた配列要素のNode.jsへのキャストの排除である。これが必要なのは、揮発性フィールドが配列からロードされて、要素に関する型情報が失われた場合である。以下の例にある(Node<K,V>)
のキャストは、今後は不要になる。
static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
}
ロケールのサポートが改善され、ネイティブイメージで複数のロケールが使用可能になった。どのロケールを含めるかは、開発者がビルド時に指定することができる。"-H:IncludeLocales=en,nl
"のように特定のロケールを追加したり、"-H:+IncludeAllLocales
"ですべてのロケールを加えたりすることが可能である。デフォルトのロケールは"-H:DefaultLocale=ja
"のように指定する。
多層コンパイル(multitier compilation)のウォームアップ時間が改善されるとともに、JavaScriptやPython、Java on TruffleといったTruffle言語で使用されるPolyglot Runtimeがデフォルトで使用できるようになった。コンパイル時間向上のために第1ティアが最適化され、小さなメソッドにはインライン化が適用されるようになった。第2ティアでは、GraalVMの最適化をすべて使用する。新たな実験的機能であるコンパイルキューは、ウォームアップ時間をさらに改善するもので、"--engine.TraversingCompilationQueue
"で使用可能になる。
Java on Trufgfleは、GraalVM 21.0で初めて紹介されて以来、いくつかの改善が行われてきた。デバッグが高速化され、機能を有効にしても問題が発生することがなくなっている。アプリケーション終了時、アプリケーションのシャットダウンフックが期待通りの動作をするようになった。
Java applications can take advantage of the guest Java Polyglot API provided by Java on Truffle. 例えば、Context.safepoint()
メソッドを使用して、ホストメソッド実行中にスレッドローカルなアクションをポールすることができる。割り込みやキャンセルのチェックにはContext
クラスを使用する。HotSpotの試験的機能として、ヒープメモリの最大値をゲストTruffle言語のメモリ使用限界に指定する機能が提供された。" --sandbox.MaxHeapMemory=<size>
"で起動する。Java Polygon APIでは、バイトバッファ、イテレータ、iterable、mapに相当するデータ構造体がサポートされるようになった。ゲスト言語でこれらの機能が実装されれば、言語のネイティブな機能のように動作する。
Enterprise Editionでは、ループにいくつかの拡張機能が使えるようになった。コンパイラがループを検出して、ハッシュコードパターンでベクトル化できるようになった。この場合のハッシュは、"c * hash + array[i]
"のように計算される。do-whileループのような反転ループも他のループと同じように、ガード最適化、ベクトル化、完全なアンローリング(ループ展開)、部分的なアンローリングを使用して最適化できるようになった。テストでは、最大40パーセントのパフォーマンス改善が示されている。whileループの各イテレーションでチェックが実行されて、インデックスが配列超を越えた場合にはArrayIndexOutOfBoundsException
がスローされるようになった。GraalVMではこの部分を、検証処理をループ前に置くことによって最適化しているが、これによってループに入らない場合でも検証処理が常に行われることになる。GraalVMはこの問題を、反転ループを使って解決している。
これら新機能の詳細は、GraalVMのリードデベロッパアドボケートであるOleg Šelajev氏と、GraalVMの開発者でプロジェクトリーダのThomas Wuerthinger氏による"Unboxing the GraalVM 21.1 release!"で確認することができる。