Linker
は、JavaプラットフォームのプレビューAPIです。
外部関数は通常、オンデマンドでロードできるライブラリに存在します。 各ライブラリは、特定のABI (アプリケーション・バイナリ・インタフェース)に準拠しています。 ABIは、ライブラリが構築されたコンパイラ、OS、およびプロセッサに関連付けられた呼び出し規則とデータ型のセットです。 たとえば、Linux/x64上のCコンパイラは通常、SystemV ABIに準拠するライブラリを構築します。
リンカーは、特定のABIで使用される呼び出し規則とデータ型について詳細に把握しています。 そのABIに準拠するライブラリの場合、リンカーはJVMで実行されているJavaコードとライブラリ内の外部関数を仲介できます。 特に次の点が重要です。
- リンカーを使用すると、Javaコードは「ダウンコール・メソッド・ハンドル」を介して外部関数とリンクできます
- リンカーを使用すると、外部関数が「アップコール・スタブ」の生成を介してJavaメソッド・ハンドルをコールできます。
libc
とlibm
。 これらのライブラリの関数は、「シンボル・ルックアップ」を介して公開されます。
nativeLinker()
メソッドは、Javaランタイムが現在実行されているOSおよびプロセッサに関連付けられたABIのリンカーを提供します。 このリンカーは、その「デフォルト・ルックアップ」を介して、Javaランタイムとともにロードも提供します。
ダウンコール・メソッドのハンドル
「外部機能のリンク」は、関数記述子、メモリー・レイアウトのセットを必要とするプロセスです。これらを組み合せて、リンクする外部関数のシグネチャを指定し、完了するとダウンコール・メソッド・ハンドル、つまりターゲット外部関数の呼出しに使用できるメソッド・ハンドルを返します。返されたメソッド・ハンドルに関連付けられたJava 「メソッド・タイプ」は、引数からのderivedPREVIEWで、関数記述子のレイアウトを返します。 ダウン・コール・メソッド・ハンドル・タイプは、追加の先行パラメータ(両方が存在する場合)によって、指定された順序で飾ることができます:
- ダウン・コール・メソッド・ハンドルが「ターゲット・アドレスを指定しない」の場合、ダウン・コール・メソッド・ハンドル・タイプは
MemorySegment
PREVIEWタイプの先行パラメータを備えており、そこからターゲットの外部関数のアドレスを導出できます。 - 関数記述子の戻りレイアウトがグループ・レイアウトの場合、結果のダウンコール・メソッド・ハンドルは、ダウンコール・メソッド・ハンドルによって返される構造体に関連付けられたメモリー・リージョンを割り当てるためにリンカー・ランタイムによって使用される
SegmentAllocator
PREVIEW型の追加の先頭パラメータを受け入れます。
アップコール・スタブ
「アップ・コール・スタブの作成」には、メソッド・ハンドルおよび関数記述子が必要です。この場合、関数記述子内のメモリー・レイアウトのセットによって、upcallスタブに関連付けられた関数ポインタのシグネチャが指定されます。指定されたメソッド・ハンドルのタイプのタイプは、アップ・コール・スタブに関連付けられているメソッド・タイプ(指定された関数記述子のderivedPREVIEW)と一致する必要があります。
アップ・コール・スタブは、タイプMemorySegment
PREVIEWのインスタンスによってモデル化されます。アップ・コール・スタブは、他のダウン・コール・メソッド・ハンドルを参照して渡すことができ、関連するscopePREVIEWを介してリリースされます。
安全に関する考慮事項
ダウンコール・メソッド・ハンドルの作成は本質的に安全ではありません。 一般的に、外部ライブラリ内のシンボルには十分なシグネチャ情報 (例、外部ファンクション・パラメータのアリティおよびタイプ)が含まれていません。 その結果、リンカーのランタイムはリンケージ・リクエストを検証できません。 クライアントが無効なリンケージ・リクエスト(例:引数のレイアウトが多すぎる関数記述子を指定)を介して取得されたダウン・コール・メソッド・ハンドルと対話する場合、このような対話の結果は不特定であり、JVMがクラッシュする可能性があります。 ダウン・コール・ハンドルの起動では、リンカー・ランタイムは、対応するレイアウトがValueLayout.ADDRESS
PREVIEWであるMemorySegment
PREVIEW型の引数A
に対して次のことを保証します:
A
のスコープは、alivePREVIEWです。 それ以外の場合、呼出しはIllegalStateException
をスローA.scope().isAccessibleBy(T) == true
などのスレッドT
で起動が発生します。 それ以外の場合、呼出しはWrongThreadException
をスローA
のスコープは、起動時の「生かし」PREVIEWです。
0
です。 ただし、戻りレイアウトが「制限なし」PREVIEWアドレス・レイアウトの場合、返されるセグメントのサイズはLong.MAX_VALUE
です。
アップ・コール・スタブを作成する場合、リンカー・ランタイムは、指定された関数記述子に対してターゲット・メソッド・ハンドルのタイプを検証し、不一致が検出されるとエラーをレポートします。 ダウンコールの場合、外部コードがアップコール・スタブに関連付けられた関数ポインタを、指定された関数記述子と互換性のない型にキャストすると、JVMがクラッシュすることがあります。 さらに、アップ・コール・スタブに関連付けられたターゲット・メソッド・ハンドルが「メモリー・セグメント」PREVIEWを返す場合、クライアントは、アップ・コールの完了後にこのアドレスが無効にならないことを確認する必要があります。 これは、通常、アップ・コールはダウン・コール・メソッド・ハンドルの起動のコンテキストで実行されるため、不特定の動作を引き起こし、JVMがクラッシュする可能性があります。
対応するレイアウトが「住所レイアウト」PREVIEWであるアップ・コール・スタブ引数は、「グローバル・スコープ」PREVIEWに関連付けられたネイティブ・セグメントです。 通常の場合、このセグメント引数のサイズは0
です。 ただし、upcall stub引数に関連付けられたレイアウトが「制限なし」PREVIEWアドレス・レイアウトの場合、セグメント引数のサイズはLong.MAX_VALUE
です。
- 実装要件:
- このインタフェースの実装は不変、スレッド・セーフ、およびvalue-basedです。
- 導入されたバージョン:
- 19
-
ネストされたクラスのサマリー
修飾子と型インタフェース説明static interface
Preview.リンカー・オプションは、関数記述子で説明される内容のほかに、リンカーへの追加のリンク要件を示すために使用されます。 -
メソッドのサマリー
修飾子と型メソッド説明一般的に使用される一連のライブラリ内のシンボル・ルックアップを返します。downcallHandle
(FunctionDescriptorPREVIEW function, Linker.OptionPREVIEW... options) 指定されたシグネチャで外部関数を呼び出すために使用できるメソッド・ハンドルを作成します。default MethodHandle
downcallHandle
(MemorySegmentPREVIEW symbol, FunctionDescriptorPREVIEW function, Linker.OptionPREVIEW... options) 指定されたシグネチャおよびアドレスで外部関数を呼び出すために使用できるメソッド・ハンドルを作成します。基礎となるネイティブ・プラットフォームに関連付けられたABIのリンカーを返します。upcallStub
(MethodHandle target, FunctionDescriptorPREVIEW function, SegmentScopePREVIEW scope) 指定されたスコープに関連付けられた関数ポインタとしてほかの外部関数に渡すことができるスタブを作成します。
-
メソッドの詳細
-
nativeLinker
基礎となるネイティブ・プラットフォームに関連付けられたABIのリンカーを返します。 基礎となるネイティブ・プラットフォームは、Javaランタイムが現在実行されているOSとプロセッサの組合せです。返されたリンカーと対話する場合、クライアントは引数および戻りレイアウトを次のように指定する
function descriptor
PREVIEWを使用して、外部関数のシグネチャを記述する必要があります:- スカラー・タイプは、適切なキャリアの「値レイアウト」PREVIEWインスタンスによってモデル化されます。 Cのスカラー型の例は、
int
,long
,size_t
などです。スカラー・タイプとそれに対応するレイアウト間のマッピングは、返されたリンカーのABIに依存 - コンポジット・タイプは、「グループ・レイアウト」PREVIEWによってモデル化されます。 返されるリンカーのABIによっては、C (e.g。
struct
またはunion
を使用)内の複合型定義のサイズおよび整列制約に準拠するために、追加のpaddingPREVIEWメンバー・レイアウトが必要になる場合があります - ポインタ・タイプは、キャリア
MemorySegment
PREVIEWを持つ「値レイアウト」PREVIEWインスタンスによってモデル化されます。 Cのポインタ型の例には、int**
とint(*)(size_t*, size_t*)
があります
前述にリストされていないレイアウトは「未サポート」です。サポートされていないレイアウトを含むファンクション記述子によって、
downcall method handle
または「アップコール・スタブ」の作成に使用するとIllegalArgumentException
がスローされます。可変個関数(例、末尾の省略記号
...
を使用して宣言されたC関数(仮パラメータ・リストの最後または空の仮パラメータ・リストを使用))は直接サポートされません。 ただし、「リンカー・オプション」PREVIEWを使用して可変引数のリストの先頭を示し、特定の変数アリティ・コール・サイトを記述する特殊な関数記述子を使用して、可変関数をリンクできます。 または、外部ライブラリで許可されている場合、クライアントはタイプVaList
PREVIEW (例、vsprintf
のように)の末尾のパラメータを渡すことで、可変個関数と対話できる可能性があります。このメソッドは「制限付き」です。 制限されたメソッドは安全ではなく、誤って使用するとJVMがクラッシュしたり、悪化したりするとメモリーが破損する可能性があります。 したがって、クライアントは制限付きメソッドに応じて屈折し、可能な場合は安全でサポートされている機能を使用する必要があります。
- APIのノート:
- 現在、OSとプロセッサの異なる組み合わせに対してリンカーを取得することはできません。
- 実装上のノート:
- 返されるリンカーに関連付けられた「デフォルト・ルックアップ」によって公開されるライブラリは、Javaランタイムが現在実行されているプロセスにロードされるネイティブ・ライブラリです。 たとえば、Linuxの場合、これらのライブラリには通常、
libc
、libm
およびlibdl
が含まれます。 - 戻り値:
- Javaランタイムが現在実行されているOSおよびプロセッサに関連付けられたABIのリンカー。
- 例外:
UnsupportedOperationException
- 基盤となるネイティブ・プラットフォームがサポートされていない場合。IllegalCallerException
- 呼び出し元が、ネイティブ・アクセスが有効になっていないモジュール内にある場合。
- スカラー・タイプは、適切なキャリアの「値レイアウト」PREVIEWインスタンスによってモデル化されます。 Cのスカラー型の例は、
-
downcallHandle
default MethodHandle downcallHandle(MemorySegmentPREVIEW symbol, FunctionDescriptorPREVIEW function, Linker.OptionPREVIEW... options) 指定されたシグネチャおよびアドレスで外部関数を呼び出すために使用できるメソッド・ハンドルを作成します。指定されたメソッド・タイプの戻り型が
MemorySegment
の場合、結果のメソッド・ハンドルには、SegmentAllocator
PREVIEW型の追加のプレフィクス・パラメータがあります。これは、リンカーが値によって返される構造体を割り当てる際に使用されます。このメソッドの呼出しは、次のコードと同じです:
linker.downcallHandle(function).bindTo(symbol);
- パラメータ:
symbol
- ターゲット関数のアドレス。function
- ターゲット関数の関数記述子。options
- リンカーのオプション。- 戻り値:
- ダウンコール・メソッド・ハンドル。 メソッド・ハンドル・タイプは「推測」です
- 例外:
IllegalArgumentException
- 指定された関数記述子がこのリンカーでサポートされていない場合、またはシンボルがMemorySegment.NULL
PREVIEWの場合IllegalArgumentException
- リンカー・オプションの無効な組み合わせが指定されている場合。
-
downcallHandle
MethodHandle downcallHandle(FunctionDescriptorPREVIEW function, Linker.OptionPREVIEW... options) 指定されたシグネチャで外部関数を呼び出すために使用できるメソッド・ハンドルを作成します。 結果のメソッド・ハンドルは、MemorySegment
PREVIEW型の外部関数エントリ・ポイントに対応するプレフィクス・パラメータ(最初のパラメータとして)を備えており、コールされるターゲット関数のアドレスを指定するために使用されます。指定された関数記述子の戻りレイアウトが
GroupLayout
PREVIEWである場合、結果のメソッドは、SegmentAllocator
PREVIEW型の追加のプレフィクス・パラメータ (addressパラメータの直後に挿入されます)を処理します。これは、リンカーが値によって返される構造体を割り当てる際に使用されます。戻されたメソッド・ハンドルは、渡された
MemorySegment
PREVIEWパラメータがMemorySegment.NULL
PREVIEWアドレスに関連付けられている場合はIllegalArgumentException
を、そのパラメータがnull
の場合はNullPointerException
をスローします。- パラメータ:
function
- ターゲット関数の関数記述子。options
- リンカーのオプション。- 戻り値:
- ダウンコール・メソッド・ハンドル。 メソッド・ハンドル・タイプは、指定された関数記述子から「推測」です。
- 例外:
IllegalArgumentException
- 指定された関数記述子がこのリンカーでサポートされていない場合。IllegalArgumentException
- リンカー・オプションの無効な組み合わせが指定されている場合。
-
upcallStub
MemorySegmentPREVIEW upcallStub(MethodHandle target, FunctionDescriptorPREVIEW function, SegmentScopePREVIEW scope) 指定されたスコープに関連付けられた関数ポインタとしてほかの外部関数に渡すことができるスタブを作成します。 このような関数ポインタを外部コードから呼び出すと、指定されたメソッド・ハンドルが実行されます。返されたメモリー・セグメントのアドレスは、新しく割り当てられたアップ・コール・スタブを指し、指定されたスコープに関連付けられます。 そのため、スコープがalivePREVIEWではなくなると、対応するアップ・コール・スタブは割り当て解除されます。
ターゲット・メソッド・ハンドルは例外をスローしません。 ターゲット・メソッド・ハンドルが例外をスローすると、VMはゼロ以外の終了コードで終了します。 例外の捕捉が原因でVMが中断しないように、クライアントは、
Throwable
を捕捉するtry/catchブロック内のターゲット・メソッド・ハンドル内のすべてのコードをラップできます。たとえば、MethodHandles.catchException(MethodHandle, Class, MethodHandle)
メソッド・ハンドル・コンビネータを使用し、対応するcatchブロックで必要に応じて例外を処理します。- パラメータ:
target
- ターゲット・メソッド・ハンドル。function
- upcallスタブ関数記述子。scope
- 返されるアップ・コール・スタブ・セグメントに関連付けられたスコープ。- 戻り値:
- アドレスがアップ・コール・スタブのアドレスである長さゼロのセグメント。
- 例外:
IllegalArgumentException
- 指定された関数記述子がこのリンカーでサポートされていない場合。IllegalArgumentException
- ターゲット・メソッド・ハンドルが例外をスローできると判断された場合、またはターゲット・メソッド・ハンドルにアップコール・スタブ「推測タイプ」と一致しないタイプがある場合。IllegalStateException
-scope
がalivePREVIEWでない場合。WrongThreadException
- このメソッドがスレッドT
から呼び出された場合(scope.isAccessibleBy(T) == false
など)。
-
defaultLookup
SymbolLookupPREVIEW defaultLookup()一般的に使用される一連のライブラリ内のシンボル・ルックアップを返します。各
Linker
PREVIEWは、Linker
PREVIEWでサポートされているOSとプロセッサの組合せで広く認識されているライブラリを選択します。 したがって、シンボル・ルックアップによって公開されるシンボルの正確なセットは指定されず、Linker
PREVIEWによって異なります。- 実装上のノート:
defaultLookup()
の結果は、時間の経過とともに安定している一連の記号を公開することを強くお薦めします。 以前にシンボル・ルックアップによって公開されたシンボルが公開されなくなった場合、defaultLookup()
のクライアントは失敗する可能性があります。実装者が複数のOSとプロセッサの組合せに対して
Linker
PREVIEW実装を提供する場合、defaultLookup()
の結果が、すべてのOSとプロセッサの組合せにわたって一貫した一連の記号を可能なかぎり公開することを強くお薦めします。- 戻り値:
- 一般的に使用される一連のライブラリ内のシンボルのシンボル・ルックアップ。
-
Linker
を使用できます。