GraalVMとネイティブ・コードの相互作用
GraalVM LLVMランタイムにより、ユーザーは、一般的にネイティブ・コードに直接コンパイルされる言語で記述されたコードを実行できます。通常、これらの言語では、管理対象ランタイムまたはVMの実行は必要ありません。そのため、特にコードが特定の低レベル機能を使用している場合、GraalVMの管理対象ランタイムとのこのコードの相互作用を検討する際は、特別な注意が必要です。
低レベルのシステム・コールへのアクセス制限
- シグナル処理は、次の仮定に基づいて実行されます:
- 管理対象ランタイムは、すべてのシグナルの処理を完全に制御することを前提としています。
- インストールされたシグナル・ハンドラの動作は、ネイティブの実行とは異なる場合があります。
- プロセス制御とスレッド化は、次の側面に基づいて行われます:
- GraalVMは、スレッド化が完全に制御可能と想定しています。
- マルチスレッドは、
pthreads
ライブラリ(pthread_create
など)を介してサポートされています。 clone
、fork
、vfork
などのプロセス関連のsyscallを直接使用することはサポートされていません。exec
関数ファミリはサポートされていません。
メモリー・レイアウト
GraalVMで実行されているプロセスのメモリーとスタックのレイアウトは、直接のネイティブ実行とは異なります。特に、グローバル、スタック変数などの相対位置などに関する前提はありません。
スタックの移動は、GraalVM APIを使用した場合にのみ可能です。コードとデータの間には厳密な分離があります。自己変更コードは動作しません。コードへのポインタに対する読取り、書込みおよびポインタ演算はサポートされていません。
ネイティブ・モードでのシステム・ライブラリとの相互作用
ネイティブ実行モード(デフォルト・モード)で、GraalVM LLVMランタイムで実行されているコードは、実際のネイティブ・ライブラリ(システム・ライブラリなど)へのコールを実行できます。これらのコールは、JavaのJNIコールと同様に動作し、管理された実行環境を一時的に終了します。
これらのライブラリで実行されるコードはGraalVMの制御下にはないため、このコードは基本的に何でも行うことができます。特に、マルチテキスト分離は適用されず、仮想ファイルシステムのようなGraalVM APIはバイパスされます。
これは、特に標準のCライブラリのほとんどに適用されます。
管理対象実行モード
管理対象モード(--LLVM.managed
オプションで有効化)は特別な実行モードであり、LLVMランタイムは他のすべてのGraalVMサポート対象言語と同様に管理モードで実行されます。
ノート: 管理対象モードはGraalVM Enterprise Editionでのみ使用できます。
このモードでは、設計上、ネイティブ・コードのコールおよびネイティブ・メモリーへのアクセスは許可されません。すべてのメモリーはガベージ・コレクタによって管理され、実行する必要があるすべてのコードをビットコードにコンパイルする必要があります。
ポインタ演算は、C標準で許可されている範囲でのみ可能です。特に、オーバーフローは防止されており、範囲外アクセスを介して異なる割当てにアクセスすることはできません。このような無効なアクセスはすべて、未定義の動作ではなく、実行時例外になります。
管理対象モードでは、GraalVMは仮想Linux/AMD64オペレーティング・システムをシミュレートし、C/C++標準ライブラリとしてmusl libcおよびlibc++を使用します。すべてのコードをそのシステムにコンパイルする必要があり、これを使用して、GraalVMでサポートされている任意のアーキテクチャまたはオペレーティング・システムで実行できます。Syscallは仮想化され、適切なGraalVM APIを介してルーティングされます。
ネイティブ・コードと管理対象言語間のポリグロット相互作用
LLVM言語(C/C++など)と管理対象言語(JavaScript、Python、Rubyなど)のポリグロット相互運用性を使用する場合は、手動メモリー管理に注意する必要があります。この項は、実行のネイティブ・モード(デフォルト)にのみ適用されます。管理対象モード(--LLVM.managed
オプションで有効化され、GraalVM Enterpriseでのみ使用可能)では、LLVMランタイム自体は管理対象言語のように動作し、ポリグロットの相互作用は他の管理対象言語間と同じです。
- 考慮するガベージ・コレクション・ポリシー:
- 管理対象言語のオブジェクトへのポインタはガベージ・コレクタによって管理されるため、手動で解放する必要はありません。
- 一方、LLVMコード(
malloc
など)からの割当てへのポインタは、ガベージ・コレクタの制御下になっていないため、手動で割当て解除する必要があります。
- 考慮する管理対象外ヒープ・ポリシー:
- ネイティブ・メモリー(
malloc
、データ・セクション、スレッド・ローカルなど)は、ガベージ・コレクタの制御下にはありません。 - ガベージ・コレクタによって制御される外部オブジェクトへのポインタは、直接ネイティブ・メモリーに格納できません。
- この制限の回避に使用できるハンドル関数があります(
graalvm/llvm/handles.h
を参照)。
- ネイティブ・メモリー(