インタフェースSymbolLookup

関数型インタフェース:
これは関数型インタフェースなので、ラムダ式またはメソッド参照の代入先として使用できます。

@FunctionalInterface public interface SymbolLookup
「シンボル・ルックアップ」は、1つ以上のライブラリ内のシンボルのアドレスを取得します。 シンボルは、関数やグローバル変数などの名前付きエンティティです。

シンボル・ルックアップは、特定のライブラリ (またはライブラリ)に対して作成されます。 その後、find(String)メソッドはシンボルの名前を取得し、そのライブラリ内のシンボルのアドレスを返します。

シンボルのアドレスは、長さゼロの「メモリー・セグメント」としてモデル化されます。 セグメントは次の様々な方法で使用できます:

  • Linkerに渡してダウンコール・メソッド・ハンドルを作成でき、これを使用してセグメントのアドレスで外部ファンクションをコールできます。
  • これは、基礎となる外部関数の引数として、既存のdowncall method handleRESTRICTEDに渡すことができます。
  • 別のメモリー・セグメント内で「保管済み」にできます。
  • グローバル変数(この場合は、最初にセグメントresizingRESTRICTEDが必要です)をバッキングするメモリー・リージョンにアクセスするために使用できます。

シンボル・ルックアップの取得

ファクトリ・メソッドlibraryLookup(String, Arena)RESTRICTEDおよびlibraryLookup(Path, Arena)RESTRICTEDは、オペレーティング・システムで認識されるライブラリのシンボル・ルックアップを作成します。 ライブラリは、その名前またはパスで指定されます。 ライブラリがまだロードされていない場合はロードされます。 シンボル・ルックアップ(「ライブラリ・ルックアップ」と呼ばれ、その存続期間は「アリーナ」によって制御されます)。 たとえば、指定されたアリーナが限定されたアリーナである場合、限定されたアリーナがclosedのときに、シンボル・ルックアップに関連付けられたライブラリがアンロードされます。
 try (Arena arena = Arena.ofConfined()) {
     SymbolLookup libGL = SymbolLookup.libraryLookup("libGL.so", arena); // libGL.so loaded here
     MemorySegment glGetString = libGL.findOrThrow("glGetString");
     ...
 } //  libGL.so unloaded here

以前にSystem.load(String)またはSystem.loadLibrary(String)によってJNI、i.eを介してライブラリがロードされていた場合、ライブラリは特定のクラス・ローダーにも関連付けられていました。 ファクトリ・メソッドloaderLookup()は、コール元クラス・ローダーに関連付けられたすべてのライブラリのシンボル・ルックアップを作成します:

System.loadLibrary("GL"); // libGL.so loaded here
...
SymbolLookup libGL = SymbolLookup.loaderLookup();
MemorySegment glGetString = libGL.findOrThrow("glGetString");
このシンボル・ルックアップは「ローダー・ルックアップ」と呼ばれ、クラス・ローダーに関連付けられたライブラリに関して動的です。 その後、他のライブラリがJNIを介してロードされ、クラス・ローダーに関連付けられている場合、ローダー・ルック・アッ・ルックアッププではそのシンボルが自動的に公開されます。

ローダー・ルックアップでは、System.load(String)またはSystem.loadLibrary(String)によって以前にJNI、i.eを介してロードされたライブラリ内の記号のみが公開されることに注意してください。 ローダー・ルックアップでは、ライブラリ・ルックアップの作成中にロードされたライブラリ内のシンボルは公開されません:

 libraryLookup("libGL.so", arena).find("glGetString").isPresent(); // true
 loaderLookup().find("glGetString").isPresent(); // false
ライブラリLのライブラリ・ルックアップでは、Lが以前にJNI (クラス・ローダーとの関連付けはライブラリ・ルックアップにとって重要ではありません)を介してロードされている場合でも、Lのシンボルが公開されることにも注意してください:
 System.loadLibrary("GL"); // libGL.so loaded here
 libraryLookup("libGL.so", arena).find("glGetString").isPresent(); // true

最後に、各Linkerは、そのLinkerでサポートされているOSとプロセッサの組合せで一般的に使用されるライブラリのシンボル・ルックアップを提供します。 このシンボル・ルックアップは「デフォルト・ルックアップ」と呼ばれ、クライアントが既知のシンボルのアドレスをすばやく検索するのに役立ちます。 たとえば、Linux/x64のLinkerは、デフォルトのルックアップを介してlibcのシンボルを公開することを選択できます。

 Linker nativeLinker = Linker.nativeLinker();
 SymbolLookup stdlib = nativeLinker.defaultLookup();
 MemorySegment malloc = stdlib.findOrThrow("malloc");

導入されたバージョン:
22
  • メソッドのサマリー

    修飾子と型
    メソッド
    説明
    find(String name)
    指定された名前のシンボルのアドレスを返します。
    指定された名前を持つシンボルのアドレスを返すか、例外をスローします。
    libraryLookup(String name, Arena arena)
    Restricted.
    指定された名前 (まだロードされていない場合)のライブラリをロードし、そのライブラリ内のシンボルのシンボル・ルックアップを作成します。
    libraryLookup(Path path, Arena arena)
    Restricted.
    指定されたパス (まだロードされていない場合)からライブラリをロードし、そのライブラリ内のシンボルのシンボル・ルックアップを作成します。
    呼び出し元クラス・ローダーに関連付けられたライブラリ内のシンボルのシンボル・ルックアップを返します。
    default SymbolLookup
    シンボルが見つかった場合は、このルックアップでシンボルを検索した結果を返す合成シンボル・ルックアップを返します。それ以外の場合は、ほかの検索でシンボルを検索した結果を返します。
  • メソッドの詳細

    • find

      指定された名前のシンボルのアドレスを返します。
      パラメータ:
      name - シンボル名
      戻り値:
      アドレスがシンボルのアドレスを示す長さがゼロのメモリー・セグメント(見つかった場合)
      関連項目:
    • findOrThrow

      default MemorySegment findOrThrow(String name)
      指定された名前を持つシンボルのアドレスを返すか、例外をスローします。

      これは次のコードと同等ですが、より効率的です: 宛先:

         String name = ...
         MemorySegment address = lookup.find(name)
             .orElseThrow(() -> new NoSuchElementException("Symbol not found: " + name));
      

      パラメータ:
      name - シンボル名
      戻り値:
      アドレスがシンボルのアドレスを示す長さゼロのメモリー・セグメント
      例外:
      NoSuchElementException - 指定された名前のシンボル・アドレスが見つからない場合
      導入されたバージョン:
      23
      関連項目:
    • or

      default SymbolLookup or(SymbolLookup other)
      シンボルが見つかった場合は、このルックアップでシンボルを検索した結果を返す合成シンボル・ルックアップを返します。それ以外の場合は、ほかの検索でシンボルを検索した結果を返します。
      APIのノート:
      このメソッドは、複数のシンボル・ルックアップをまとめて連鎖するために使用できます。たとえば、シンボルを複数のライブラリから順番に取得できるようにするためです:
       var lookup = SymbolLookup.libraryLookup("foo", arena)
               .or(SymbolLookup.libraryLookup("bar", arena))
               .or(SymbolLookup.loaderLookup());
      
      前述のコードは、最初に"foo"ライブラリ内のシンボルを検索するシンボル・ルックアップを作成します。 "foo"に記号が見つからない場合は、"バール"が検索されます。 最後に、シンボルが"foo"にも"バール"にもない場合、「ローダー・ルックアップ」が使用されます。
      パラメータ:
      other - この検索で見つからないシンボルの検索に使用するシンボル・ルックアップ
      戻り値:
      シンボルが見つかった場合、このルックアップでシンボルを検索した結果を返す合成シンボル・ルックアップ。それ以外の場合は、ほかのルックアップでシンボルを検索した結果を返します
    • loaderLookup

      static SymbolLookup loaderLookup()
      呼び出し元クラス・ローダーに関連付けられたライブラリ内のシンボルのシンボル・ルックアップを返します。

      ライブラリは、CLで定義されるクラスのコードからSystem.load(String)またはSystem.loadLibrary(String)を呼び出してライブラリをロードすると、クラス・ローダーCLに関連付けられます。 そのコードによってSystem.load(String)またはSystem.loadLibrary(String)がさらに起動される場合、より多くのライブラリがロードされ、CLに関連付けられます。 このメソッドによって返されるシンボル・ルックアップは常に最新です: このメソッドが返された後にロードされた場合でも、関連するクラス・ローダーに関連付けられたすべてのライブラリが反映されます。

      クラス・ローダーに関連付けられたライブラリは、クラス・ローダーがunreachableになるとアンロードされます。 このメソッドによって返されるシンボル・ルックアップは、呼出し側のクラス・ローダーが到達可能な状態を維持する自動scopeに関連付けられます。 そのため、コール元のクラス・ローダーに関連付けられたライブラリは、そのクラス・ローダーまたはそれによって取得されたセグメントのいずれかのローダー・ルックアップがアクセス可能なかぎり、ロードされた(およびそれらのシンボルが使用可能)が保持されます。

      スタック(例、JNIアタッチ・スレッドから直接コールされる場合)にコール元フレームがないコンテキストからこのメソッドがコールされる場合、コール元クラス・ローダーはデフォルトで「システム・クラス・ローダー」に設定されます。

      戻り値:
      呼び出し元のクラス・ローダーに関連付けられたライブラリ内のシンボルのシンボル・ルックアップ
      関連項目:
    • libraryLookup

      static SymbolLookup libraryLookup(String name, Arena arena)
      libraryLookupは、Javaプラットフォームの制限付きメソッドです。
      プログラムは、制限付きメソッドへのアクセスが有効になっている場合にのみlibraryLookupを使用できます。
      制限されたメソッドは安全ではありません。不適切に使用した場合、JVMがクラッシュまたはメモリーが破損する場合があります。
      指定された名前 (まだロードされていない場合)のライブラリをロードし、そのライブラリ内のシンボルのシンボル・ルックアップを作成します。 返されるライブラリ・ルックアップの存続期間は、指定されたアリーナによって制御されます。 たとえば、提供されたアリーナが限定されたアリーナである場合、提供された限定されたアリーナがclosedの場合、返されたルックアップに関連付けられたライブラリはアンロードされます。
      実装上のノート:
      ライブラリ名の解決プロセスはOS固有です。 たとえば、POSIX準拠のOSでは、ライブラリ名はそのOSのdlopen関数の指定に従って解決されます。 Windowsでは、ライブラリ名はLoadLibrary関数の指定に従って解決されます。
      パラメータ:
      name - シンボルを検索するライブラリの名前
      arena - 返されたルックアップから取得されたシンボルに関連付けられたアリーナ
      戻り値:
      指定された名前のシンボルをライブラリ内で検索するのに適した新しいシンボル・ルックアップ
      例外:
      IllegalStateException - arena.scope().isAlive() == falseの場合
      WrongThreadException - arenaが限定アリーナで、このメソッドがアリーナの所有者スレッド以外のスレッドTからコールされる場合
      IllegalArgumentException - nameが有効なライブラリを識別しない場合
      IllegalCallerException - 呼び出し元が、ネイティブ・アクセスが有効になっていないモジュール内にある場合
    • libraryLookup

      static SymbolLookup libraryLookup(Path path, Arena arena)
      libraryLookupは、Javaプラットフォームの制限付きメソッドです。
      プログラムは、制限付きメソッドへのアクセスが有効になっている場合にのみlibraryLookupを使用できます。
      制限されたメソッドは安全ではありません。不適切に使用した場合、JVMがクラッシュまたはメモリーが破損する場合があります。
      指定されたパス (まだロードされていない場合)からライブラリをロードし、そのライブラリ内のシンボルのシンボル・ルックアップを作成します。 返されるライブラリ・ルックアップの存続期間は、指定されたアリーナによって制御されます。 たとえば、提供されたアリーナが限定されたアリーナである場合、提供された限定されたアリーナがclosedの場合、返されたルックアップに関連付けられたライブラリはアンロードされます。
      実装上のノート:
      Linuxでは、このファクトリ・メソッドによって提供される機能および返されるシンボル・ルックアップは、dlopendlsymおよびdlclose関数を使用して実装されます。
      パラメータ:
      path - シンボルを検索するライブラリのパス
      arena - 返されたルックアップから取得されたシンボルに関連付けられたアリーナ
      戻り値:
      指定されたパスを持つライブラリ内のシンボルを見つけるのに適した新しいシンボル・ルックアップ
      例外:
      IllegalStateException - arena.scope().isAlive() == falseの場合
      WrongThreadException - arenaが限定アリーナで、このメソッドがアリーナの所有者スレッド以外のスレッドTからコールされる場合
      IllegalArgumentException - pathがデフォルトのファイル・システムの有効なライブラリを指していない場合
      IllegalCallerException - 呼び出し元が、ネイティブ・アクセスが有効になっていないモジュール内にある場合