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

インタフェースVaList


public sealed interface VaList
VaListは、JavaプラットフォームのプレビューAPIです。
プレビュー機能が有効な場合のみ、プログラムでVaListを使用できます。
プレビュー機能は、今後のリリースで削除するか、Javaプラットフォームの永続機能にアップグレードすることができます。
C va_listの機能と同様に、可変引数リストを作成および操作するヘルパー・クラス。

可変引数リストは、次のようにmake(Consumer, SegmentScope)ファクトリを使用して作成できます:

 VaList vaList = VaList.make(builder ->
                                    builder.addVarg(C_INT, 42)
                                           .addVarg(C_DOUBLE, 3.8d));
作成後、クライアントは可変引数リストに関連付けられたプラットフォーム依存の「メモリー・セグメント」を取得でき、その後、C va_list型を使用してネイティブ関数をターゲットとする「downcallメソッド・ハンドル」PREVIEWに渡すことができます。

変数引数リストをモデリングする外部メモリー・セグメントの内容には、「不安」で変数引数リストを作成することによって、次のようにアクセスできます:

 void upcall(int n, MemorySegment vaListSegment) {
    try (Arena arena = Arena.openConfined()) {
        VaList vaList = VaList.ofAddress(vaListSegment.address(), arena.scope());
        VaList copy = vaList.copy();
        int i = vaList.nextVarg(C_INT);
        double d = vaList.nextVarg(C_DOUBLE);
        // and again
        int i = copy.nextVarg(C_INT);
        double d = copy.nextVarg(C_DOUBLE);
     }
 }
前述のメソッドでは、変数引数リストをモデリングする外部セグメントを受信します。セグメントの内容は、セグメント・アドレスから新しい変数引数リストを作成することによってアクセスされます。 要素にアクセスする前に、変数引数リストが2番目のリストに最初にコピーされることに注意してください: これにより、要素を2回反復できます。 変数引数リストの要素には、nextVarg(ValueLayout.OfInt)およびnextVarg(ValueLayout.OfDouble)を使用してアクセスします。 これらのメソッド(VaListPREVIEWクラスの他のアクセス・メソッド)は、アクセスする必要がある要素のレイアウトを取得し、必要なすべての整列チェックおよびエンディアン変換を実行します。

C仕様 (C99標準6.5.2.2関数コール - アイテム6を参照) に従って、可変個呼び出しへの引数は、整数昇格 (C99標準6.3.1.1 - アイテム2を参照)によって整数型を消去し、doubleのすべてのfloat引数を消去する'デフォルトの引数プロモーション'によって消去されます。

そのため、このインタフェースでは、intdoubleおよびlongに適合するその他のタイプの読取りのみがサポートされます。

安全に関する考慮事項

誤ったメモリー・レイアウトを使用して変数引数リストを介して値にアクセスすると、予期しない動作が発生します。 たとえば、変数引数リストが現在Cのint値を指している場合、nextVarg(ValueLayout.OfLong)を使用してアクセスすることは不正です。 同様に、skip(MemoryLayout...)を使用して変数引数リストにアクセスし、ValueLayout.OfIntPREVIEW以外のレイアウトを指定することは不正です。 このような不正なアクセスは実装によって検出されず、変数引数リストが破損して後続のアクセスの動作も未定義になる可能性があります。

クライアントは、変数引数リストの空間境界外の要素にアクセスできます。 可変引数リストの実装では、範囲外の読み取りをベスト・エフォートで検出しようとします。

この検出が成功するかどうかは、変数引数リストの作成に使用されるファクトリ・メソッドによって異なります:

  • make(Consumer, SegmentScope)を使用して「安全」が作成された変数引数リストは、範囲外の読取りを検出できます
  • 「不安」が作成された変数引数リストは、ofAddress(long, SegmentScope)を使用して範囲外の読取りを検出できません

このクラスはスレッド・セーフではなく、すべてのアクセスは単一のスレッド (変数アリティ・リストの取得に使用されるスコープに関係なく)内で行う必要があります。

導入されたバージョン:
19
  • メソッドの詳細

    • nextVarg

      int nextVarg(ValueLayout.OfIntPREVIEW layout)
      次の値をintとして読み取って、この変数引数リストの位置を進めます。 このメソッドの動作は、Cのva_arg関数と同じです。
      パラメータ:
      layout - 読み取る値のレイアウト。
      戻り値:
      この変数引数リストから読み取られるint値。
      例外:
      IllegalStateException - この変数引数リストに関連付けられたスコープがalivePREVIEWでない場合。
      WrongThreadException - このメソッドがスレッドTから呼び出された場合(segment().scope().isAccessibleBy(T) == falseなど)。
      NoSuchElementException - out-of-bounds読取りが検出された場合。
    • nextVarg

      long nextVarg(ValueLayout.OfLongPREVIEW layout)
      次の値をlongとして読み取って、この変数引数リストの位置を進めます。 このメソッドの動作は、Cのva_arg関数と同じです。
      パラメータ:
      layout - 読み取る値のレイアウト。
      戻り値:
      この変数引数リストから読み取られるlong値。
      例外:
      IllegalStateException - この変数引数リストに関連付けられたスコープがalivePREVIEWでない場合。
      WrongThreadException - このメソッドがスレッドTから呼び出された場合(segment().scope().isAccessibleBy(T) == falseなど)。
      NoSuchElementException - out-of-bounds読取りが検出された場合。
    • nextVarg

      double nextVarg(ValueLayout.OfDoublePREVIEW layout)
      次の値をdoubleとして読み取って、この変数引数リストの位置を進めます。 このメソッドの動作は、Cのva_arg関数と同じです。
      パラメータ:
      layout - 値のレイアウト
      戻り値:
      この変数引数リストから読み取られるdouble値。
      例外:
      IllegalStateException - この変数引数リストに関連付けられたスコープがalivePREVIEWでない場合。
      WrongThreadException - このメソッドがスレッドTから呼び出された場合(segment().scope().isAccessibleBy(T) == falseなど)。
      NoSuchElementException - out-of-bounds読取りが検出された場合。
    • nextVarg

      次のアドレス値を読み取り、ネイティブ・セグメントにラップして、この変数引数リストの位置を進めます。 このメソッドの動作は、Cのva_arg関数と同じです。 返されるセグメントのベースMemorySegment.address()PREVIEWは、変数引数リストから読み取られた値に設定され、セグメントは「グローバル・スコープ」PREVIEWに関連付けられます。 通常の状況では、返されるセグメントのサイズは0です。 ただし、指定されたレイアウトが「制限なし」PREVIEWアドレス・レイアウトの場合、返されるセグメントのサイズはLong.MAX_VALUEです。
      パラメータ:
      layout - 読み取る値のレイアウト。
      戻り値:
      addressPREVIEWがこの変数引数リストから読み取られる値であるネイティブ・セグメント。
      例外:
      IllegalStateException - この変数引数リストに関連付けられたスコープがalivePREVIEWでない場合。
      WrongThreadException - このメソッドがスレッドTから呼び出された場合(segment().scope().isAccessibleBy(T) == falseなど)。
      NoSuchElementException - out-of-bounds読取りが検出された場合。
    • nextVarg

      指定されたロケータとともに割り当てられた新しいMemorySegmentに次のコンポジット値を読み取り、この変数引数リストの位置を進めます。 このメソッドの動作は、Cのva_arg関数と同じです。 指定されたグループ・レイアウトは、C構造体または共用体タイプに対応している必要があります。

      返されるセグメントでの値の読取り方法は、ABIに依存: メンバー・レイアウトL_1, L_2, ... L_nを持つグループ・レイアウトでこのメソッドを呼び出すことは、L_1, L_2, ... L_nの各レイアウトに対してnextVargへの個別のコールを実行する意味的に等しくなるとはかぎりません。

      このメソッドによって返されるメモリー・セグメントは、指定されたSegmentAllocatorPREVIEWを使用して割り当てられます。

      パラメータ:
      layout - 読み取る値のレイアウト。
      allocator - 変数引数リストの内容がコピーされるセグメントの作成に使用するロケータ。
      戻り値:
      この変数引数リストから読み取られるMemorySegment値。
      例外:
      IllegalStateException - この変数引数リストに関連付けられたスコープがalivePREVIEWでない場合。
      WrongThreadException - このメソッドがスレッドTから呼び出された場合(segment().scope().isAccessibleBy(T) == falseなど)。
      NoSuchElementException - out-of-bounds読取りが検出された場合。
    • skip

      void skip(MemoryLayoutPREVIEW... layouts)
      指定されたメモリー・レイアウトを持つ多数の要素をスキップし、この変数引数リストの位置を先に進めます。
      パラメータ:
      layouts - スキップする値のレイアウト。
      例外:
      IllegalStateException - この変数引数リストに関連付けられたスコープがalivePREVIEWでない場合。
      WrongThreadException - このメソッドがスレッドTから呼び出された場合(segment().scope().isAccessibleBy(T) == falseなど)。
      NoSuchElementException - out-of-bounds読取りが検出された場合。
    • copy

      この変数引数リストを現在の位置にコピーし、この変数引数リストと同じスコープに関連付けられた新しい変数引数リストにコピーします。 このメソッドの動作は、Cのva_copy関数と同じです。

      コピーは、元の変数引数リストの状態に影響を与えずに、変数引数リスト要素を現在の位置から移動する場合に役立ちます。基本的に、要素を複数回移動できます。

      戻り値:
      この変数引数リストのコピー。
      例外:
      IllegalStateException - この変数引数リストに関連付けられたスコープがalivePREVIEWでない場合。
      WrongThreadException - このメソッドがスレッドTから呼び出された場合(segment().scope().isAccessibleBy(T) == falseなど)。
    • segment

      この変数引数リストに関連付けられた長さゼロの「メモリー・セグメント」PREVIEWを返します。 返されるメモリー・セグメントの内容はプラットフォームに依存します。 変数引数リストの内容を反復するときに、返されるセグメントの内容を更新するかどうか、およびその方法もプラットフォームに依存します。
      戻り値:
      この変数引数リストに関連付けられた長さがゼロの「メモリー・セグメント」PREVIEW
    • ofAddress

      static VaListPREVIEW ofAddress(long address, SegmentScopePREVIEW scope)
      指定されたアドレス値およびスコープから変数引数リストを作成します。 このアドレスは、通常、外部メモリー・セグメント・インスタンスでMemorySegment.address()PREVIEWをコールして取得されます。 指定されたスコープは、返される変数引数リストのライフサイクルを決定: 返される変数引数リストはアクセスできなくなり、スコープがalivePREVIEWではなくなると、関連付けられたオフ・ヒープ・メモリー・リージョンが解放されます。

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

      パラメータ:
      address - 変数引数リストのアドレス。
      scope - 返される変数引数リストに関連付けられたスコープ。
      戻り値:
      指定されたアドレス値から始まるメモリーのオフ・ヒープ・リージョンに支えられた新しい変数引数リスト。
      例外:
      IllegalStateException - scopealivePREVIEWでない場合。
      WrongThreadException - このメソッドがスレッドTから呼び出された場合(scope.isAccessibleBy(T) == falseなど)。
      UnsupportedOperationException - 基盤となるネイティブ・プラットフォームがサポートされていない場合。
      IllegalCallerException - 呼び出し元が、ネイティブ・アクセスが有効になっていないモジュール内にある場合。
    • make

      指定されたスコープを持つビルダー (VaList.BuilderPREVIEWを参照してください)を使用して、変数引数リストを作成します。 指定されたスコープは、返される変数引数リストのライフサイクルを決定: 返される変数引数リストはアクセスできなくなり、スコープがalivePREVIEWではなくなると、関連付けられたオフ・ヒープ・メモリー・リージョンが解放されます。

      作成されたvaリストに要素が追加されていない場合、このメソッドはempty()と同じものを返します。

      実装上のノート:
      このメソッドを使用して作成された変数引数リストは、out-of-bounds読取りを検出できます。
      パラメータ:
      actions - 基礎となる変数引数リストの要素を指定するために使用できるビルダー(VaList.BuilderPREVIEWを参照してください)のコンシューマ。
      scope - 新しい変数アリティ・リストに関連付けるスコープ。
      戻り値:
      新しい変数引数リスト。
      例外:
      UnsupportedOperationException - 基盤となるネイティブ・プラットフォームがサポートされていない場合。
      IllegalStateException - scopealivePREVIEWでない場合。
      WrongThreadException - このメソッドがスレッドTから呼び出された場合(scope.isAccessibleBy(T) == falseなど)。
    • empty

      static VaListPREVIEW empty()
      「グローバル・スコープ」PREVIEWに関連付けられた空の変数引数リストを返します。 結果の変数引数リストには引数が含まれず、segment()copy()を除くすべての操作でUnsupportedOperationExceptionがスローされます。
      戻り値:
      空の変数引数リスト。
      例外:
      UnsupportedOperationException - 基盤となるネイティブ・プラットフォームがサポートされていない場合。