Faster warmup, smaller downloads, JDK 16 — GraalVM 21.1 is here!

原文はこちら。
The original entry was written by Oleg Šelajev (Developer advocate for GraalVM at Oracle Labs).
https://medium.com/graalvm/graalvm-21-1-96e18f6806bf

毎回のリリース同様、GraalVMコミュニティの皆様には、フィードバック、コラボレーション、GitHubのIssue、プルリクエスト、そしてGraalVMの情報を広めていただき、大変感謝しております。皆さんのおかげで、GraalVMはますます成功し、改善され続けるプロジェクトとなっています。

GraalVM 21.1が以下のページからダウンロードいただけるようになりました。

この記事では、GraalVM 21.1で最も重要な改善点について取り上げたいと思います。特定のコンポーネントに興味があるとか、変更点の詳細を知りたい方は、21.1のリリースノートをチェックしてください。

GraalVM 21.1.0 Release Notes
https://www.graalvm.org/release-notes/21_1/

テキストよりも動画で学びたいという方向けに、GraalVM 21.1のアップデートについて説明しているライブストリームの録画もございます。

Platform Updates

Oracle GraalVM Enterprise Edition 21.1はOracle JDK 1.8.0_291とOracle JDK 11.0.11ベースです。GraalVM Community Edition 21.1はOpenJDK 1.8.0_292とOpenJDK 11.0.11ベースです。

GraalVM 21.1では、JDK 16.0.1ベースの新たな実験的バイナリを両Editionで導入しています。

実験的(experimental)とは、他のディストリビューションバージョンがどのようなステータスであるかに関わらず、JDK 16ベースのバイナリの全てのコンポーネントが実験的なものとみなされます。

JavaアプリケーションのJITモードは、これらのビルドでおそらく最もテストされた機能なので、GraalVMコンパイラでJavaアプリケーションを実行することに関心があったり、最新の他のOpenJDKビルドで現在JVMCIコンパイラを使っていたりする場合、GraalVMバイナリの試用を検討してください。JDK 16ベースのGraalVMバイナリには、最新のOpenJDKの変更点と最新のGraalVMコンパイラの変更点が含まれており、両方の世界の最善のものです。

Java 16は現在のJavaリリースであり、来るLTSのJava 17のサポートを提供することを楽しみにしています。

なお、老朽化したmacOS 10.7のビルドインフラの廃止に伴い、JDK 8ベースのGraalVM Community Editionのリリースはビルドされなくなりました。

GraalVM 21.1に含まれるNode.jsは、14.16.1にアップデートされました。ほとんどのユーザーに推奨します。

GraalVMのNodeに関しては、もう一つ重要な変更点があります。GraalVM 21.1では、Node.jsのサポートは、GraalVMのCoreには含まれなくなりました。現在、gu install nodejsコマンドでインストールできる独立したコンポーネントになっています。JavaScriptのサポートは引き続きCoreに含まれていますが、Node.jsのサポートだけは別個にインストール可能となっています。この変更は、スピードとわかりやすさのためのもので、基本となるGraalVMのダウンロードサイズを縮小すること、主にメインのJDKとしてGraalVMを使用したいと考えているユーザーの混乱を軽減することを目的としています。

GraalVM CE 21.1 download is smaller than in the previous release.

Compiler Updates

コンパイラのアップデートは、GraalVMでサポートされている様々な言語のパフォーマンスを支えるものであるため、GraalVM全体のパフォーマンスを向上させるものであり、特にエキサイティングなものです。

21.1では、特に興味深いコンパイラの改良が2個あります。

1つは、x86におけるシーケンシャルな揮発性書き込みの際に、不要なメモリバリアを排除するという新しい最適化です。コードがインライン化された後に、多数の揮発性書き込みが連続して発生することがあります。GraalVMコンパイラは、シーケンス内の最後の書き込み以外のメモリバリアを省略することで、ConcurrentHashMap.transfer()などのメソッドの高速化に寄与します。

もう一つの改善点、これは完全に新たな最適化というよりは修正に近いのですが、類似のワークロードのパフォーマンス向上に役立つものです。以下の例は、同じくConcurrentHashMapのメソッドで、配列からObjectを取得するためにUnsafeが使用されています。この修正により、GraalVMのコンパイラはキャストを排除します。

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); 
}

Loops Updates

本リリースでは、GraalVM Enterprise コンパイラにおいて、hashCodeに類似したパターンを持つループのベクトル化をサポートしています。ハッシュコードは次のようなイディオムで計算されることが多々あります。

hash = c * hash + array[i]

これをコンパイラが認識し、ベクトル化できるようになりました。

また、反転ループに関連するGraalVM Enterpriseの2つの新機能を紹介します。まず、コンパイラはinverted loop(反転ループ)をcounted loop(カウントされたループ)として検出します。

以下は、終端でカウントされる、反転ループの例です。

This release includes support in the GraalVM Enterprise compiler for vectorizing loops that have the hashCode-like pattern. Hashcode is often computed with an idiom like: hash = c * hash + array[i] , which the compiler can now recognize and vectorize.

We also want to highlight two new GraalVM Enterprise features related to inverted loops. First, the compiler detects inverted loops as counted loops:

Here’s an example of a tail-counted, inverted:

int i = 0; 
do {    
  // loop body    
  i++; 
} while (i < limit);

ループ制限のチェックを、ループ本体の最後で実施していることに着目してください。GraalVM Enterpriseは、このようなループをcounted loopとして検出し、他のcounted loopと同様に分析・最適化し、full unrolling(完全なループ展開)、partial unrolling(部分ループ展開)、guard optimization(ガード最適化)、vectorization(ベクトル化)の対象とすることができるようになりました。この新機能は、次のオプションで無効化できます。

-Dgraal.DetectInvertedLoopsAsCounted=false

ホットコードパスに反転ループがあるアプリケーションでは、最大40%のパフォーマンスの向上が確認されています。反転ループが頻繁に使用される顕著な例として、GraalVMのLLVMビットコードランタイムがあります。このランタイムはLLVM IRをコンパイルしており、Clangの内部ループ表現は反転ループに似ていることが多々あります。

この点に関する2つ目の改善点は、斬新なループ反転の最適化です。この改善は、通常のループから反転ループを生成するためのコンパイラサポートをGraalVM Enterpriseに追加するものです。反転ループは、ループの最初にカウントする通常のループに比べて、命令レベルの並列性や最適化機能に優れた特性を持っています。
このループの例を考えてみましょう。

int limit = ...; // e.g. a parameter int i = 0; 
while (i < limit) {   
  array[i] += 10;   
  i++; 
}

このループの反復ごとに、インデックスの境界チェックを行い、配列長超過時は、ArayIndexOutOfBoundsExceptionを投げる必要があります。GraalVM Enterpriseのガードモーション最適化では、ループの前に巻き上げ可能な最適化済みガードを生成します。

int limit = ...; 
int i = 0; // transfer to interpreter to raise ArrayIndexOutOfBoundsException
if (limit >= array.length || limit < 0) deoptimize();  
while (i < limit) { 
  array[i] += 10;   
i++; 
}

このコードの欠点は、ループに入ることがなくてもガードをチェックする点です。これは、時間とリソースの最適な使い方ではありません。これは、ループに入るかどうかを判断するチェックを複製することで解決できますが、余計な作業が増え、コードサイズも大きくなってしまいます。しかし、ループを反転させることで、次のようになります。

int limit = ...;
int i = 0;
if (i < limit) {
  // landing pad
  if (limit >= array.length || limit < 0) deoptimize();
  do {
    array[i] += 10;
    i++;
  } while (i < limit);
}

これにより、元のループが実行された場合にのみ実行されるループの前に、ガードモーションやループ不変式の自然な着地点ができます。反転ループを使用したマイクロベンチマークでは、最大30%の性能向上が確認されています。これは素晴らしいことです。

Native Image

毎回のリリースと同様、Native Imageには新機能に加えて、数多くの問題点の修正や互換性の改善が行われています。

GraalVM 21.1では、Native Imageで複数のロケールをサポートするようになりました。ビルド時に、生成される実行ファイルに含まれるべきロケールを指定できるようになりました。例えば、デフォルトのロケールをドイツ語に変更し、フランス語と英語も含める場合は、

-H:DefaultLocale=de -H:IncludeLocales=fr,en

とします。すべてのロケールを含めるには、

-H:+IncludeAllLocales

を使用します。ResourceBundleはデフォルトでは選択されたすべてのロケールに対応していますが、バンドルのリクエスト時にロケール固有のサブストリング(部分文字列)を指定することで変更できます。

次のリリースでは、ロケール設定を支援するNative Image構成支援エージェントのアップデートや、外部ストレージからのバンドルの読み込みなど、さらなる改善が予定されています。

また、--enable-all-security-servicesオプションの使用は廃止されました。ビルド時に静的解析によってセキュリティサービスの使用が検出されると、自動的に登録されるようになったため、このオプションは必要なくなりました。

今回のリリースでは、WindowsにおけるNative Imageのサポートが改善されました。Native Image でビルドされたアプリケーションでは、パラメータに対してfile globbingを行うようになりました。Globbingとは、*? などの標準的な特殊文字を解釈して、ファイル名を照合することです。

また、その他の優れた追加機能もあります。具体的には、複数のアーティファクトを生成するためにNative Imageビルドのレポートが追加されました。ビルド結果を<image-name>.build_artifacts.txtファイルに書き込みます。また、同じプロセスで複数の異なるNative Imageにコンパイル済みのアーティファクトを使用できます。例えば、Native Imageでビルドされたアプリケーションは、Native Imageで生成された共有ライブラリを使用できます。

Polyglot Runtime

JavaScript、Python、Ruby、R、Webassembly、Java on Truffle、TruffleSqueak、LLVM bitcodeなど、いずれかのTruffle言語を使用している場合には、polyglot runtimeの変更は重要です。

GraalVM 21.1のpolyglot runtimeでは、デフォルトで多層コンパイルが有効になっています。この機能は、20.3で実験的オプションとして初めて導入されました。この機能を有効にすると、Truffleはpolyglot言語に対して多層コンパイルを使用します。第1層は、コンパイル速度に最適化されており、GraalVMコンパイラのエコノミー設定を再利用して、自明なメソッドだけメソッド・インライニングで高速なコンパイルを行います。第2層は、GraalVMのコンパイラ最適化をすべて有効にしてコンパイルし、第1層のコンパイルが完了した後に実行されます。ベンチマークの結果、ほとんどの言語でウォームアップが大幅に改善されました。

以下の記事で、GraalVM 21.1の多層コンパイルの詳細について、様々なベンチマークやTruffle言語への影響を調べています。

Multi-Tier Compilation in GraalVM
https://medium.com/graalvm/multi-tier-compilation-in-graalvm-5fbc65f92402
https://logico-jp.io/2021/04/25/multi-tier-compilation-in-graalvm/

多層コンパイルの柔軟性をサポートするために、21.1 ではコンパイルのしきい値を設定する新しい実験的なフラグも導入しています。--engine.FirstTierCompilationThresholdは第1層のしきい値を設定し、--engine.LastTierCompilationThresholdは第2層のしきい値を設定します。多層コンパイルが無効な場合は、--engine.SingleTierCompilationThreshold を使用できます。既存のオプションである --engine.CompilationThreshold は現在非推奨となっており、将来のリリースで削除される予定です。

状況にもよりますし、ワークロードやコードベースの詳細に大きく依存しますが、Truffle 言語のスタートアップおよびウォームアップのパフォーマンスは、以前のリリースに比べて大幅に改善されるはずです。

For Polyglot Embedding/Guest Language Users

JavaアプリケーションからTruffle言語を使用している場合、ここに記載されている変更点は、あなたにとって重要なものになるかもしれません。

GraalVM 21.1で追加された興味深い新機能の1つに、ゲスト言語のセーフポイントの実装があります。Context.safepoint()を使用して、ホスト・メソッドの実行中にポリグロット・コンテキストのスレッド・ローカル・アクションを協調的にポーリングします。これにより、Context内から中断やキャンセルをチェックできます。
このリリースでは、ゲスト言語のメモリ使用量を制限するために、GraalVM Enterpriseに新しい実験的なサンドボックス・オプションが追加されました。ゲストアプリケーションが実行中に保持できる最大のヒープメモリを制御する --sandbox.MaxHeapMemory=<size> オプションを使用します。この機能は現在、HotSpot でのみサポートされています。ヒープメモリ制限の使用方法の詳細については、サンドボックスのドキュメントを参照してください。

Configure Sandbox Resource Limits
https://www.graalvm.org/reference-manual/embed-languages/#configure-sandbox-resource-limits

Truffle のデータ構造のpolyglotサポートに、byte buffer型、iterator/iterable型、map型の 3 つのデータ構造が追加されました。個々の言語でも変更を実装する必要があるため、これらの機能の各言語でのサポートは異なる場合がありますが、簡単に言うと以下のようになります。

  • java.nio.ByteBufferの実装は、ネイティブのゲスト言語のバッファのように動作します。
  • java.util.Iteratorjava.util.Iterableの実装は、ゲスト言語のイテレータのように動作します。
  • java.util.Mapの実装は、ゲスト言語のハッシュマップのように見えるように処理されます。
  • ゲスト言語のイテレータおよびハッシュ マップは、Value.as(Iterator.class)Value.as(Map.class)を使用してJavaのIterator、HashMapにマッピングできます。
  • ValueクラスのAPIには、これらの新しいデータ構造にアクセスするための新しいメソッド(Value.hasBufferElements()Value.isIterator()Value.hasIterator()、およびValue.hasHashEntries())が含まれています。

もちろん、これらの機能はHostAccess.BuilderのメソッドであるallowMapAccessallowBufferAccessallowIteratorAccessallowIterableAccessで制御できます。つまり、言語実装がサポートしていれば、Java Mapをコンテキストに渡して、ネイティブのゲスト言語マップであるかのようにそのエントリにアクセスすることができます。

JavaScript

プラットフォームのアップデートでもお伝えしましたが、GraalVMがサポートするNode.jsのバージョンが14.16.1にアップデートされました。今回のリリースでは、nodenpmのバイナリは基本ダウンロードに含まれておらず、別途インストールできるようになっています。
Node.jsコンポーネントのインストールは、他のオプションコンポーネントと同様にguユーティリティを使用して行います:

gu install nodejs
[opc@ol8-demo 21.1]$ gu install nodejs
Downloading: Component catalog from www.graalvm.org
Processing Component: Graal.nodejs
Downloading: Component nodejs: Graal.nodejs  from github.com
Installing new component: Graal.nodejs (org.graalvm.nodejs, version 21.1.0)
... 

JVMモード(--jvmコマンドラインオプションで有効化できます)ではないpolyglotプログラムの実行にnodeを使いたい場合は、アクセスしたいすべての言語を含むようにpolyglot共有ライブラリを再ビルドする必要があることに注意してください。これは、gu rebuild images を実行するか、gu installの出力にある指示に従うことで実施できます。JVMモードでは、インストールされたすべての言語が動的にロードされるため、再ビルドは必要ありません。

GraalVM 21.1のJavaScriptには、Truffleによるイテレータ、イテレート、バイトバッファのサポートが含まれています。

  • Value APIのhasIterator()getIterator()hasIteratorNextElement()getIteratorNextElement()を使ってJavaScriptのイテレータを使用できます。
  • 他の言語のiterableなオブジェクトを、GraalVMのJavaScriptランタイムで反復処理できます(例:for-ofループの利用、その逆も可能)。
  • ホストのByteBuffersや他言語のバッファをJavaScriptの型付き配列で利用できます(例:new Uint8Array(foreignBuffer)DataViewで使用でき、コピーは不要)。
  • Value APIを使ってArrayBufferにアクセスできるようになりました(readBuffer*、writeBuffer*)。

Mapのサポートも含まれているので、for in/ofループやnew Map(hash)Array.from(hash)などでマップを反復処理できます。さらに、--js.foreign-hash-propertiesオプションが有効になっていれば(デフォルトで有効)、hash[key]hash.key{…hash}で外部のハッシュマップにもアクセスできるようになります。このサポートにより、以下の例が動作するようになりました。

import org.graalvm.polyglot.*;
import org.graalvm.polyglot.Context.Builder;
import org.graalvm.polyglot.proxy.*;
import java.util.*;
public class Main {
public static void main(String[] args) {
try (Context context = Context.newBuilder()
.allowAllAccess(true)
.build()) {
Map<String, Object> javaMap = new HashMap<>();
javaMap.put("name", "GraalVM");
javaMap.put("version", 21.1);
context.getBindings("js").putMember("javaMap", javaMap);
Value jsObject = context.eval("js",
"{ " +
"print(javaMap.name);" +
"print(javaMap.version);" +
" new Map([['hello','world'],[1, 42]]);"+
"}");
var map = jsObject.as(Map.class);
System.out.println(map + "; " + map.get("hello"));
}
}
}
view raw Main.java hosted with ❤ by GitHub

Example of using new Truffle support for hashes in Graaljs 21.1

出力結果を見てみると、非常に面白いですね。

[opc@ol8-demo 21.1]$ javac Main.java && java Main 
GraalVM 
21.1 
Map(2) {"hello" => "world", 1 => 42}; world

これらの優れた改良に加えて、このリリースではWebAssembly JavaScript Interfaceの最初の実験的バージョンが追加されました。これにより、JavaScript内からWebAssemblyプログラムを呼び出せます。この機能は --js.webassembly オプションで有効になります。

Ruby

毎回のリリース同様、GraalVM 21.1には、Ruby 2.7のより完全なサポートを含む、大量のRuby互換性とパフォーマンスに関する作業が反映されています(残存作業はGitHub issueでご覧いただけます)。

Ruby 2.7 support #2004
https://github.com/oracle/truffleruby/issues/2004

多層コンパイルがデフォルトで有効になり、ウォームアップが大幅に改善されました。その他、再帰のチェック、乱数生成、クラス変数を使用するいくつかのケース、irbirbへのコードの貼り付けなど、すべての項目がこのリリースで改善されました。

GraalVM 21.1では、C拡張のサポートも改善されています。静的ライブラリにリンクするC拡張を使用するgemのインストールは、GraalVM LLVMツールチェーンをPATHに前置することで動作するようになりました。このリリースでは、GraalVMは、CRubyと同様に、nokogiriをインストールする際に、ベンダーのlibxml2libxsltのgemをデフォルトで使用するようになり、対応するシステムパッケージが不要になりました。

また、TruffleRubyのスタンドアロンビルドを使用している場合は、以前使用していたJDK 8からJDK 11をベースにしていることにご注意ください。

Python

GraalVM 21.1のPython向けの重要な改善点の1つは、Javaサブクラスのサポート強化と、Jythonの移行パスを改善するための新しい相互運用APIです。JavaからのPython型の反復処理、PythonコードでのJava例外のキャッチと再スロー、PythonからのJava抽象クラスとインタフェースの実装などは、Jythonの機能としてリクエストが多数ありますが、これをGraalVMが提供することで、移行を容易にします。

もう一つの非常にエキサイティングな追加機能はSSLのサポートです。CPythonのようにpipでパッケージとその依存関係をインストールできるようになりました。

$ graalpython -m venv env 
We're not using symlinks in a Graal Python venv $ source env/bin/activate $ pip install pygal 
Collecting pygal   
Downloading pygal-2.4.0-py2.py3-none-any.whl (127 kB)      
|████████████████████████████████| 127 kB 983 kB/s 
Looking for Graal Python patches for pygal 
Installing collected packages: pygal 
Looking for Graal Python patches for pygal 
Successfully installed pygal-2.4.0

また、Posix APIのための完全にネイティブなバックエンドが新たに追加され、ファイルシステムアクセスのパフォーマンスと互換性が向上しました。

GraalVM 21.1のPythonサポートにおけるエキサイティングな新機能のリストは、GIL(Global Interpreter Lock)によるマルチスレッドの追加で締めくくります。GraalPythonはCPythonと同程度のマルチスレッディングをサポートしますが、ほとんどのワークロードでは並列処理ではなく同時処理のみとなります。

LLVM bitcode runtime

いつものように、LLVMランタイムにはたくさんの性能向上と互換性の修正がありますが、21.1では、いくつかの新機能もあります。

例えば、JavaScriptのArrayBufferのような、外部の “buffer-like”のオブジェクトへのポインタは、ネイティブバッファのように透過的にアクセスできます。

GraalVMは、Polyglot APIに加えて、通常のdlopenによるビットコードモジュールのロードをサポートしました。

ネイティブモードを完全に削除したGraalVMまたはネイティブの実行ファイルのビルドをサポートするオプションが追加され、--llvm.managed モードが唯一の利用可能なオプションとなりました。これにより、特定のシナリオにおけるセキュリティが向上します。

FastR

このリリースのGraalVMのRの実装は、ほとんどが互換性のための作業でした。

GraalVM 21.1では、FastRをRバージョン4.0.3にアップグレードしており、FastRランタイムはR 4.0.3とほぼ互換性があります。また、基本パッケージと推奨パッケージの新バージョンへの移行と、R 4.0.3の新機能の一部を実装しています。すべての詳細については、変更履歴をご覧ください。

変更履歴
https://github.com/oracle/fastr/blob/master/CHANGELOG.md#2110

また、install.packagesでデフォルトで使用されるCRANスナップショットを 2021-02-01 にアップグレードしました。FastRで最も人気のあるパッケージの新バージョンのサポートは現在進行中で、dplyr 1.0.3、ggplot 3.3.3、knitr 1.31の既知の問題については今後のリリースで改善される予定です。

WebAssembly

GraalVM 21.1では、互換性とパフォーマンスという2つの主要な改善テーマがありました。この哲学に従って、JavaScriptとWebAssemblyは以前よりもはるかによく統合され、JavaScriptからWebAssemblyを呼び出すことができるようになりました。また、基本的なWASI機能が実装されたことで、ファイル操作やTruffleファイルシステムレイヤーを通じてファイルシステムへのアクセスが可能になり、パフォーマンス面でも驚くべき結果が得られました。

スタンドアロンのGraalWasmランチャーの速度向上やGraalVM上のWebAssemblyのピークパフォーマンスの向上に加えて、主なハイライトはインタープリタの10倍以上のパフォーマンス向上ですが、これは短時間で実行されるプログラムやJITコンパイルを起動するほどではない数回しか呼び出されないコードで最も顕著に現れます。これは訓練ではありません。繰り返しますが、10倍のパフォーマンス向上です。

Java on Truffle

GraalVM 21.0のリリースは、Truffle上のJavaの最初のリリースでした。それ以来、私たちは互換性に集中し、典型的な開発シナリオで典型的なアプリケーションを実行するために有用であることを確認しました。

例えば、instrumentを有効にした場合の大幅な速度低下を修正したので、Java on Truffle上でのアプリケーションのデバッグが遅く感じなくなっています。これだけでなく、Java Debug Wire Protocol (JDWP) のサポートで修正が必要なエッジケースがありました。その甲斐あって、デバッガを有効にしたアプリケーションが200倍という驚異的なスピードで実行されることもありました。

また、シグナル・ハンドラのサポートも追加され、アプリケーションに登録されたシャットダウン・フックが、アプリケーションの停止時に期待通りに実行されるようになりました。

強化されたHotSwap機能の改善にも常に取り組んでいます。例えば、今回のリリースでは、reflectiveなアクセスやMethodHandlesがメソッドの変更に追従するようになりました。

Tools

ツールは、GraalVMエコシステムの非常に重要な部分です。すべてのリリースにおいて、デバッガやプロファイラなど、GraalVMディストリビューションの一部であるツールを改善することで、developer experienceを向上させようとしています。GraalVM 21.1も例外ではありません。

例えば、VisualVMはJDK 16でも動作するようになり、Apple M1チップでの動作もサポートしています。

私たちは、GraalVM、Java、Micronautアプリケーションでの作業を容易にするための機能を集めたVS Code GraalVM Extensionsの新バージョンを発表します。

Visual Studio Code Extensions
https://www.graalvm.org/tools/vscode/

  • ユニットテスト結果の可視化機能を追加しました。
VS Code visualizing results of the unit tests in the testing view
  • Micronautのサポート強化
    設定ファイルのYAMLサポートとコンテンツ支援、Javaコード編集機能の強化
Configure Micronaut applications in VS Code with the improved content assist
  • Javaコード向けに新たにサポートされたリファクタリング機能の追加
  • Micronautプロジェクト用のDockerビルドコマンドのサポートを追加

Whew!

通常のリリース時の記事に比べて非常に長くなってしまいましたが、これらはGraalVM 21.1のエキサイティングな改善点のほんの一部です。

再度申し上げますが、いつも通りWebサイトからダウンロードできます。

ご意見・ご感想をお待ちしておりますので、ご遠慮なくお寄せください。チームへの連絡方法はいくつかありますので、お好きな方法をお選びください。Slack、GitHub、Twitterの中からお好きなものをお選びください。みなさまからの情報をお待ちしています。ではまた!

Slack invitation
https://www.graalvm.org/slack-invitation
GitHub Issues
https://github.com/oracle/graal
Twitter
https://twitter.com/graalvm

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中