モジュール java.base
パッケージ java.lang.foreign

インタフェースLinker


public sealed interface Linker
Linkerは、JavaプラットフォームのプレビューAPIです。
プレビュー機能が有効な場合のみ、プログラムでLinkerを使用できます。
プレビュー機能は、今後のリリースで削除するか、Javaプラットフォームの永続機能にアップグレードすることができます。
リンカーは、Javaコードから外部関数にアクセスでき、外部関数からJavaコードにアクセスできます。

外部関数は通常、オンデマンドでロードできるライブラリに存在します。 各ライブラリは、特定のABI (アプリケーション・バイナリ・インタフェース)に準拠しています。 ABIは、ライブラリが構築されたコンパイラ、OS、およびプロセッサに関連付けられた呼び出し規則とデータ型のセットです。 たとえば、Linux/x64上のCコンパイラは通常、SystemV ABIに準拠するライブラリを構築します。

リンカーは、特定のABIで使用される呼び出し規則とデータ型について詳細に把握しています。 そのABIに準拠するライブラリの場合、リンカーはJVMで実行されているJavaコードとライブラリ内の外部関数を仲介できます。 特に次の点が重要です。

さらに、リンカーはABIに準拠するライブラリ内の外部関数を検索する方法も提供します。 各リンカーは、ABIに関連付けられたOSとプロセッサの組み合わせで一般的に使用されるライブラリ・セットを選択します。 たとえば、Linux/x64のリンカーは2つのライブラリを選択できます: libclibm これらのライブラリの関数は、「シンボル・ルックアップ」を介して公開されます。

nativeLinker()メソッドは、Javaランタイムが現在実行されているOSおよびプロセッサに関連付けられたABIのリンカーを提供します。 このリンカーは、その「デフォルト・ルックアップ」を介して、Javaランタイムとともにロードも提供します。

ダウンコール・メソッドのハンドル

「外部機能のリンク」は、関数記述子、メモリー・レイアウトのセットを必要とするプロセスです。これらを組み合せて、リンクする外部関数のシグネチャを指定し、完了するとダウンコール・メソッド・ハンドル、つまりターゲット外部関数の呼出しに使用できるメソッド・ハンドルを返します。

返されたメソッド・ハンドルに関連付けられたJava 「メソッド・タイプ」は、引数からのderivedPREVIEWで、関数記述子のレイアウトを返します。 ダウン・コール・メソッド・ハンドル・タイプは、追加の先行パラメータ(両方が存在する場合)によって、指定された順序で飾ることができます:

  • ダウン・コール・メソッド・ハンドルが「ターゲット・アドレスを指定しない」の場合、ダウン・コール・メソッド・ハンドル・タイプはMemorySegmentPREVIEWタイプの先行パラメータを備えており、そこからターゲットの外部関数のアドレスを導出できます。
  • 関数記述子の戻りレイアウトがグループ・レイアウトの場合、結果のダウンコール・メソッド・ハンドルは、ダウンコール・メソッド・ハンドルによって返される構造体に関連付けられたメモリー・リージョンを割り当てるためにリンカー・ランタイムによって使用されるSegmentAllocatorPREVIEW型の追加の先頭パラメータを受け入れます。

アップコール・スタブ

「アップ・コール・スタブの作成」には、メソッド・ハンドルおよび関数記述子が必要です。この場合、関数記述子内のメモリー・レイアウトのセットによって、upcallスタブに関連付けられた関数ポインタのシグネチャが指定されます。

指定されたメソッド・ハンドルのタイプのタイプは、アップ・コール・スタブに関連付けられているメソッド・タイプ(指定された関数記述子のderivedPREVIEW)と一致する必要があります。

アップ・コール・スタブは、タイプMemorySegmentPREVIEWのインスタンスによってモデル化されます。アップ・コール・スタブは、他のダウン・コール・メソッド・ハンドルを参照して渡すことができ、関連するscopePREVIEWを介してリリースされます。

安全に関する考慮事項

ダウンコール・メソッド・ハンドルの作成は本質的に安全ではありません。 一般的に、外部ライブラリ内のシンボルには十分なシグネチャ情報 (例、外部ファンクション・パラメータのアリティおよびタイプ)が含まれていません。 その結果、リンカーのランタイムはリンケージ・リクエストを検証できません。 クライアントが無効なリンケージ・リクエスト(例:引数のレイアウトが多すぎる関数記述子を指定)を介して取得されたダウン・コール・メソッド・ハンドルと対話する場合、このような対話の結果は不特定であり、JVMがクラッシュする可能性があります。 ダウン・コール・ハンドルの起動では、リンカー・ランタイムは、対応するレイアウトがValueLayout.ADDRESSPREVIEWであるMemorySegmentPREVIEW型の引数Aに対して次のことを保証します: 戻りレイアウトが「住所レイアウト」PREVIEWである関数記述子から作成されたダウン・コール・メソッド・ハンドルは、「グローバル・スコープ」PREVIEWに関連付けられたネイティブ・セグメントを返します。 通常の状況では、返されるセグメントのサイズは0です。 ただし、戻りレイアウトが「制限なし」PREVIEWアドレス・レイアウトの場合、返されるセグメントのサイズはLong.MAX_VALUEです。

アップ・コール・スタブを作成する場合、リンカー・ランタイムは、指定された関数記述子に対してターゲット・メソッド・ハンドルのタイプを検証し、不一致が検出されるとエラーをレポートします。 ダウンコールの場合、外部コードがアップコール・スタブに関連付けられた関数ポインタを、指定された関数記述子と互換性のない型にキャストすると、JVMがクラッシュすることがあります。 さらに、アップ・コール・スタブに関連付けられたターゲット・メソッド・ハンドルが「メモリー・セグメント」PREVIEWを返す場合、クライアントは、アップ・コールの完了後にこのアドレスが無効にならないことを確認する必要があります。 これは、通常、アップ・コールはダウン・コール・メソッド・ハンドルの起動のコンテキストで実行されるため、不特定の動作を引き起こし、JVMがクラッシュする可能性があります。

対応するレイアウトが「住所レイアウト」PREVIEWであるアップ・コール・スタブ引数は、「グローバル・スコープ」PREVIEWに関連付けられたネイティブ・セグメントです。 通常の場合、このセグメント引数のサイズは0です。 ただし、upcall stub引数に関連付けられたレイアウトが「制限なし」PREVIEWアドレス・レイアウトの場合、セグメント引数のサイズはLong.MAX_VALUEです。

実装要件:
このインタフェースの実装は不変、スレッド・セーフ、およびvalue-basedです。
導入されたバージョン:
19
  • メソッドの詳細

    • nativeLinker

      static LinkerPREVIEW nativeLinker()
      基礎となるネイティブ・プラットフォームに関連付けられたABIのリンカーを返します。 基礎となるネイティブ・プラットフォームは、Javaランタイムが現在実行されているOSとプロセッサの組合せです。

      返されたリンカーと対話する場合、クライアントは引数および戻りレイアウトを次のように指定するfunction descriptorPREVIEWを使用して、外部関数のシグネチャを記述する必要があります:

      • スカラー・タイプは、適切なキャリアの「値レイアウト」PREVIEWインスタンスによってモデル化されます。 Cのスカラー型の例は、int, long, size_tなどです。スカラー・タイプとそれに対応するレイアウト間のマッピングは、返されたリンカーのABIに依存
      • コンポジット・タイプは、「グループ・レイアウト」PREVIEWによってモデル化されます。 返されるリンカーのABIによっては、C (e.g。structまたはunionを使用)内の複合型定義のサイズおよび整列制約に準拠するために、追加のpaddingPREVIEWメンバー・レイアウトが必要になる場合があります
      • ポインタ・タイプは、キャリアMemorySegmentPREVIEWを持つ「値レイアウト」PREVIEWインスタンスによってモデル化されます。 Cのポインタ型の例には、int**int(*)(size_t*, size_t*)があります

      前述にリストされていないレイアウトは「未サポート」です。サポートされていないレイアウトを含むファンクション記述子によって、downcall method handleまたは「アップコール・スタブ」の作成に使用するとIllegalArgumentExceptionがスローされます。

      可変個関数(例、末尾の省略記号...を使用して宣言されたC関数(仮パラメータ・リストの最後または空の仮パラメータ・リストを使用))は直接サポートされません。 ただし、「リンカー・オプション」PREVIEWを使用して可変引数のリストの先頭を示し、特定の変数アリティ・コール・サイトを記述する特殊な関数記述子を使用して、可変関数をリンクできます。 または、外部ライブラリで許可されている場合、クライアントはタイプVaListPREVIEW (例、vsprintfのように)の末尾のパラメータを渡すことで、可変個関数と対話できる可能性があります。

      このメソッドは制限付きです。 制限されたメソッドは安全ではなく、誤って使用するとJVMがクラッシュしたり、悪化したりするとメモリーが破損する可能性があります。 したがって、クライアントは制限付きメソッドに応じて屈折し、可能な場合は安全でサポートされている機能を使用する必要があります。

      APIのノート:
      現在、OSとプロセッサの異なる組み合わせに対してリンカーを取得することはできません。
      実装上のノート:
      返されるリンカーに関連付けられた「デフォルト・ルックアップ」によって公開されるライブラリは、Javaランタイムが現在実行されているプロセスにロードされるネイティブ・ライブラリです。 たとえば、Linuxの場合、これらのライブラリには通常、libclibmおよびlibdlが含まれます。
      戻り値:
      Javaランタイムが現在実行されているOSおよびプロセッサに関連付けられたABIのリンカー。
      例外:
      UnsupportedOperationException - 基盤となるネイティブ・プラットフォームがサポートされていない場合。
      IllegalCallerException - 呼び出し元が、ネイティブ・アクセスが有効になっていないモジュール内にある場合。
    • downcallHandle

      default MethodHandle downcallHandle(MemorySegmentPREVIEW symbol, FunctionDescriptorPREVIEW function, Linker.OptionPREVIEW... options)
      指定されたシグネチャおよびアドレスで外部関数を呼び出すために使用できるメソッド・ハンドルを作成します。

      指定されたメソッド・タイプの戻り型がMemorySegmentの場合、結果のメソッド・ハンドルには、SegmentAllocatorPREVIEW型の追加のプレフィクス・パラメータがあります。これは、リンカーが値によって返される構造体を割り当てる際に使用されます。

      このメソッドの呼出しは、次のコードと同じです:

      linker.downcallHandle(function).bindTo(symbol);
      

      パラメータ:
      symbol - ターゲット関数のアドレス。
      function - ターゲット関数の関数記述子。
      options - リンカーのオプション。
      戻り値:
      ダウンコール・メソッド・ハンドル。 メソッド・ハンドル・タイプは推測です
      例外:
      IllegalArgumentException - 指定された関数記述子がこのリンカーでサポートされていない場合、またはシンボルがMemorySegment.NULLPREVIEWの場合
      IllegalArgumentException - リンカー・オプションの無効な組み合わせが指定されている場合。
    • downcallHandle

      MethodHandle downcallHandle(FunctionDescriptorPREVIEW function, Linker.OptionPREVIEW... options)
      指定されたシグネチャで外部関数を呼び出すために使用できるメソッド・ハンドルを作成します。 結果のメソッド・ハンドルは、MemorySegmentPREVIEW型の外部関数エントリ・ポイントに対応するプレフィクス・パラメータ(最初のパラメータとして)を備えており、コールされるターゲット関数のアドレスを指定するために使用されます。

      指定された関数記述子の戻りレイアウトがGroupLayoutPREVIEWである場合、結果のメソッドは、SegmentAllocatorPREVIEW型の追加のプレフィクス・パラメータ (addressパラメータの直後に挿入されます)を処理します。これは、リンカーが値によって返される構造体を割り当てる際に使用されます。

      戻されたメソッド・ハンドルは、渡されたMemorySegmentPREVIEWパラメータがMemorySegment.NULLPREVIEWアドレスに関連付けられている場合はIllegalArgumentExceptionを、そのパラメータがnullの場合はNullPointerExceptionをスローします。

      パラメータ:
      function - ターゲット関数の関数記述子。
      options - リンカーのオプション。
      戻り値:
      ダウンコール・メソッド・ハンドル。 メソッド・ハンドル・タイプは、指定された関数記述子から推測です。
      例外:
      IllegalArgumentException - 指定された関数記述子がこのリンカーでサポートされていない場合。
      IllegalArgumentException - リンカー・オプションの無効な組み合わせが指定されている場合。
    • upcallStub

      指定されたスコープに関連付けられた関数ポインタとしてほかの外部関数に渡すことができるスタブを作成します。 このような関数ポインタを外部コードから呼び出すと、指定されたメソッド・ハンドルが実行されます。

      返されたメモリー・セグメントのアドレスは、新しく割り当てられたアップ・コール・スタブを指し、指定されたスコープに関連付けられます。 そのため、スコープがalivePREVIEWではなくなると、対応するアップ・コール・スタブは割り当て解除されます。

      ターゲット・メソッド・ハンドルは例外をスローしません。 ターゲット・メソッド・ハンドルが例外をスローすると、VMはゼロ以外の終了コードで終了します。 例外の捕捉が原因でVMが中断しないように、クライアントは、Throwableを捕捉するtry/catchブロック内のターゲット・メソッド・ハンドル内のすべてのコードをラップできます。たとえば、MethodHandles.catchException(MethodHandle, Class, MethodHandle)メソッド・ハンドル・コンビネータを使用し、対応するcatchブロックで必要に応じて例外を処理します。

      パラメータ:
      target - ターゲット・メソッド・ハンドル。
      function - upcallスタブ関数記述子。
      scope - 返されるアップ・コール・スタブ・セグメントに関連付けられたスコープ。
      戻り値:
      アドレスがアップ・コール・スタブのアドレスである長さゼロのセグメント。
      例外:
      IllegalArgumentException - 指定された関数記述子がこのリンカーでサポートされていない場合。
      IllegalArgumentException - ターゲット・メソッド・ハンドルが例外をスローできると判断された場合、またはターゲット・メソッド・ハンドルにアップコール・スタブ推測タイプと一致しないタイプがある場合。
      IllegalStateException - scopealivePREVIEWでない場合。
      WrongThreadException - このメソッドがスレッドTから呼び出された場合(scope.isAccessibleBy(T) == falseなど)。
    • defaultLookup

      SymbolLookupPREVIEW defaultLookup()
      一般的に使用される一連のライブラリ内のシンボル・ルックアップを返します。

      LinkerPREVIEWは、LinkerPREVIEWでサポートされているOSとプロセッサの組合せで広く認識されているライブラリを選択します。 したがって、シンボル・ルックアップによって公開されるシンボルの正確なセットは指定されず、LinkerPREVIEWによって異なります。

      実装上のノート:
      defaultLookup()の結果は、時間の経過とともに安定している一連の記号を公開することを強くお薦めします。 以前にシンボル・ルックアップによって公開されたシンボルが公開されなくなった場合、defaultLookup()のクライアントは失敗する可能性があります。

      実装者が複数のOSとプロセッサの組合せに対してLinkerPREVIEW実装を提供する場合、defaultLookup()の結果が、すべてのOSとプロセッサの組合せにわたって一貫した一連の記号を可能なかぎり公開することを強くお薦めします。

      戻り値:
      一般的に使用される一連のライブラリ内のシンボルのシンボル・ルックアップ。