モジュール jdk.incubator.foreign
パッケージ jdk.incubator.foreign

インタフェースCLinker

すべてのスーパー・インタフェース:
SymbolLookup

public sealed interface CLinker extends SymbolLookup
Cリンカーは、Cアプリケーション二項インタフェースの(ABI)呼び出し規則を実装します。 このインタフェースのインスタンスは、JVMターゲット・プラットフォームC ABIに準拠するネイティブ・ライブラリの外部ファンクションをリンクするために使用できます。 Cリンカーは2つの主な機能を提供: まず、Javaコードでlink外部関数を「downcallメソッド・ハンドル」というようにlinkできます。次に、ネイティブ・コードで「upcallスタブ」の生成を介してJavaメソッド・ハンドルをコールできます。

サポートされていないプラットフォームでは、このクラスはExceptionInInitializerErrorでの初期化に失敗します。

特に指定がないかぎり、null引数、またはこのクラスのメソッドに1つ以上のnull要素を含む配列引数を渡すと、NullPointerExceptionがスローされます。

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

「外部関数のリンク」は、関数記述子、一連のメモリー・レイアウトを必要とするプロセスであり、これらをまとめて、リンクする外部関数のシグネチャを指定し、完了するとダウン・コール・メソッド・ハンドル、つまりターゲット・ネイティブ関数の起動に使用できるメソッド・ハンドルを返します。 返されるメソッド・ハンドルに関連付けられたJava 「メソッド・タイプ」は、引数からderivedで、関数記述子のレイアウトを返します。 さらに具体的には、関数記述子の各レイアウトLでは、次に示すように、対応するキャリアCが推測されます:

  • LValueLayoutで、キャリアEがある場合、次の2つのケースがあります:
    • Lがパラメータ位置で発生し、EMemoryAddress.classの場合、C = Addressable.class ;
    • otherwise, C = E;
  • または、LGroupLayoutの場合、CMemorySegment.classに設定されます

前述のとおりに導出されたダウン・コール・メソッド・ハンドル・タイプは、追加の先行パラメータによって、両方が存在する場合、指定された順序で装飾される場合があります:

  • downcallメソッド・ハンドルが「ネイティブ・シンボルを指定しない」に設定されている場合、downcallメソッド・ハンドル・タイプには、ターゲット・ネイティブ関数のアドレスを導出できるNativeSymbol型の先行パラメータがあります。
  • 関数記述子のリターン・レイアウトがグループ・レイアウトである場合、結果のdowncallメソッド・ハンドルは、タイプSegmentAllocatorの追加先行パラメータを受け入れます。これは、リンカー・ランタイムによって、downcallメソッド・ハンドルによって返される構造に関連付けられたメモリー・リージョンを割り当てるために使用されます。

仮パラメータ・リストの最後に末尾に省略記号(...)を付けるか、空の仮パラメータ・リストを使用してCで宣言された可変個関数は、直接サポートされません。 ただし、variadic関数記述子を使用して、ネイティブの可変個引数関数をリンクできます。この関数記述子では、特定の変数のアリティ・コール・サイトの特殊なシグネチャがフルに記述されます。 また、外部ライブラリで許可されている場合、クライアントは、VaList型の後続のパラメータを渡すことによって、可変引数のメソッドと対話することもできます。

アップ・コール・スタブ

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

指定されたメソッド・ハンドルのタイプは、upcallスタブに関連付けられたJava 「メソッド・タイプ」と一致する必要があります。これは、引数から導出され、関数記述子のレイアウトを返します。 さらに具体的には、関数記述子の各レイアウトLでは、次に示すように、対応するキャリアCが推測されます:

  • LValueLayoutで、キャリアEがある場合、次の2つのケースがあります:
    • Lが返品位置で発生し、EMemoryAddress.classの場合、C = Addressable.class ;
    • otherwise, C = E;
  • または、LGroupLayoutの場合、CMemorySegment.classに設定されます
アップ・コール・スタブはNativeSymbolタイプのインスタンスによってモデル化されます。アップ・コール・スタブは、他のダウン・コール・メソッドを参照することで(NativeSymbolAddressableインタフェースを実装)を処理し、不要になった場合はscopeを介してreleasedにできます。

システム・ルック・アップ

このクラスは、SymbolLookupインタフェースを実装します。そのため、クライアントは、このリンカーに関連付けられた標準ライブラリで「探す」記号を使用できます。 ルックアップに使用できる記号のセットは、プラットフォームおよびオペレーティング・システムに依存するため、指定されていません。

安全に関する考慮事項

ダウン・コール・メソッド・ハンドルの取得は安全ではありません。 ネイティブ・ライブラリ内のシンボルには、通常、十分なシグネチャ情報 (例:アーリティおよびネイティブ関数パラメータのタイプ)が含まれていません。 その結果、リンカーのランタイムはリンケージ・リクエストを検証できません。 クライアントが無効なリンケージ・リクエスト(例:引数のレイアウトが多すぎる関数記述子を指定)を介して取得されたダウン・コール・メソッド・ハンドルと対話する場合、このような対話の結果は不特定であり、JVMがクラッシュする可能性があります。 ダウン・コール・ハンドルの起動時に、リンカー・ランタイムにより、メモリー・リソースR (タイプMemorySegmentNativeSymbolまたはVaList)である引数に対して次のことが保証されます:
  • Rのリソース・スコープはaliveです。 それ以外の場合、呼出しはIllegalStateExceptionをスロー
  • 起動は、Rのリソース・スコープのowningと同じスレッドで行われます(指定されたスコープが限定されている場合)。 それ以外の場合、呼出しはIllegalStateExceptionをスロー
  • Rのスコープは、起動時の「生存」 (クローズできません)です。

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

実装要件:
このインタフェースの実装は不変、スレッド・セーフ、およびvalue-basedです。
  • メソッドのサマリー

    修飾子と型
    メソッド
    説明
    指定された型の外部メソッド・ハンドルを取得し、指定された関数記述子を装備します。これは、動的に提供されるネイティブ・シンボル内のアドレスでターゲットの外部関数を呼び出すために使用できます。
    default MethodHandle
    指定された型の外部メソッド・ハンドルを取得し、指定された関数記述子を装備します。これは、指定されたネイティブ・シンボル内のアドレスでターゲット外部関数を呼び出すために使用できます。
    static MethodType
    downcallType(FunctionDescriptor functionDescriptor)
    指定された関数記述子に関連付けられたdowncallメソッド・ハンドルtypeを取得します。
    lookup(String name)
    このリンカーに関連付けられた標準ライブラリのシンボルを検索します。
    static CLinker
    現在のプラットフォームのCリンカーを返します。
    指定されたスコープを持つネイティブ・スタブを、他の外部関数(関数ポインタとして)に渡すことができます。このようなファンクション・ポインタをネイティブ・コードからコールすると、指定されたメソッド・ハンドルが実行されます。
    static MethodType
    upcallType(FunctionDescriptor functionDescriptor)
    指定された関数記述子を持つupcallスタブに関連付けられたメソッド・ハンドルtypeを取得します。
  • メソッドの詳細

    • systemCLinker

      static CLinker systemCLinker()
      現在のプラットフォームのCリンカーを返します。

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

      戻り値:
      このシステムのリンカー。
      例外:
      IllegalCallerException - このメソッドへのアクセスがモジュールMから発生し、コマンドライン・オプション--enable-native-accessがない場合、またはモジュール名Mが名前なしモジュールの場合はALL-UNNAMEDは説明しません。
    • lookup

      default Optional<NativeSymbol> lookup(String name)
      このリンカーに関連付けられた標準ライブラリのシンボルを検索します。 ルックアップに使用できる記号のセットは、プラットフォームおよびオペレーティング・システムに依存するため、指定されていません。
      定義:
      インタフェースSymbolLookup内のlookup
      パラメータ:
      name - シンボル名。
      戻り値:
      このリンカーに関連付けられた標準ライブラリのシンボル。
    • downcallHandle

      default MethodHandle downcallHandle(NativeSymbol symbol, FunctionDescriptor function)
      指定された型の外部メソッド・ハンドルを取得し、指定された関数記述子を装備します。これは、指定されたネイティブ・シンボル内のアドレスでターゲット外部関数を呼び出すために使用できます。

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

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

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

      パラメータ:
      symbol - downcallシンボル。
      function - 関数記述子。
      戻り値:
      downcallメソッド・ハンドル。 メソッド・ハンドル・タイプは推測です
      例外:
      IllegalArgumentException - 指定された記述子に順序またはパディング・レイアウトが含まれている場合、または記号がMemoryAddress.NULLの場合
      関連項目:
    • downcallHandle

      MethodHandle downcallHandle(FunctionDescriptor function)
      指定された型の外部メソッド・ハンドルを取得し、指定された関数記述子を装備します。これは、動的に提供されるネイティブ・シンボル内のアドレスでターゲットの外部関数を呼び出すために使用できます。 結果のメソッド・ハンドルは、NativeSymbol型の外部関数のエントリ・ポイントに対応するプレフィクス・パラメータ(最初のパラメータとして)を特徴としています。

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

      返されたメソッド・ハンドルは、渡されたネイティブ・シンボルがMemoryAddress.NULLアドレスに関連付けられている場合はIllegalArgumentExceptionをスローし、ネイティブ・シンボルがnullの場合はNullPointerExceptionをスローします。

      パラメータ:
      function - 関数記述子。
      戻り値:
      downcallメソッド・ハンドル。 メソッド・ハンドル・タイプは、指定された関数記述子から推測です。
      例外:
      IllegalArgumentException - 指定された記述子にシーケンスまたはパディングのレイアウトが含まれている場合。
      関連項目:
    • upcallStub

      NativeSymbol upcallStub(MethodHandle target, FunctionDescriptor function, ResourceScope scope)
      指定されたスコープを持つネイティブ・スタブを、他の外部関数(関数ポインタとして)に渡すことができます。このようなファンクション・ポインタをネイティブ・コードからコールすると、指定されたメソッド・ハンドルが実行されます。

      返される関数ポインタは、指定されたスコープに関連付けられます。 このようなスコープが閉じられると、対応するネイティブ・スタブが割り当て解除されます。

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

      パラメータ:
      target - ターゲット・メソッド・ハンドル。
      function - 関数記述子。
      scope - upcallスタブ・スコープ。
      戻り値:
      ネイティブ・スタブ・シンボル。
      例外:
      IllegalArgumentException - 指定された記述子に順序またはパディング・レイアウトが含まれている場合、またはターゲット・メソッド・ハンドルが例外をスローできることが判明した場合、またはターゲット・メソッド・ハンドルにupcallスタブ推測タイプと一致しないタイプがあるかどうか。
      IllegalStateException - scopeがすでにクローズされている場合、またはscopeを所有するスレッド以外のスレッドからアクセスが発生した場合。
    • downcallType

      static MethodType downcallType(FunctionDescriptor functionDescriptor)
      指定された関数記述子に関連付けられたdowncallメソッド・ハンドルtypeを取得します。
      パラメータ:
      functionDescriptor - 関数記述子。
      戻り値:
      downcallメソッドは、指定された関数記述子に関連付けられたtypeを処理します。
      例外:
      IllegalArgumentException - 関数記述子内の1つ以上のレイアウトがサポートされていない場合、(例:シーケンス・レイアウトまたはパディング・レイアウトの場合)。
    • upcallType

      static MethodType upcallType(FunctionDescriptor functionDescriptor)
      指定された関数記述子を持つupcallスタブに関連付けられたメソッド・ハンドルtypeを取得します。
      パラメータ:
      functionDescriptor - 関数記述子。
      戻り値:
      指定された関数記述子を持つupcallスタブに関連付けられたメソッド・ハンドルtype
      例外:
      IllegalArgumentException - 関数記述子内の1つ以上のレイアウトがサポートされていない場合、(例:シーケンス・レイアウトまたはパディング・レイアウトの場合)。