インタフェースArena

すべてのスーパー・インタフェース:
AutoCloseable, SegmentAllocator

public interface Arena extends SegmentAllocator, AutoCloseable
アリーナは、ネイティブ・メモリー・セグメントのライフサイクルを制御し、柔軟な割当てとタイムリな割当て解除の両方を提供します。

アリーナにはscopeがあります。 - 「アリーナ・スコープ」 アリーナによって割り当てられたすべてのセグメントは、アリーナ・スコープに関連付けられます。 そのため、アリーナは、割り当てられているすべてのメモリー・セグメントの一時的な範囲を決定します。

さらに、アリーナは、割り当てられたメモリー・セグメントへのアクセスを特定のスレッドに対して「制限付き」にするかどうかも決定します。 アリーナはSegmentAllocatorであり、クライアントがネイティブ・セグメントを取得するために使用できるいくつかの割当てメソッドを備えています。

最も単純なアリーナは、「グローバル・アリーナ」です。 グローバル・アリーナには、「無制限有効期間」があります。 グローバル・アリーナのスコープはグローバル・スコープです。 そのため、グローバル・アリーナに割り当てられたネイティブ・セグメントには常にアクセス可能で、メモリーのバッキング・リージョンは割当て解除されません。 さらに、グローバル・アリーナで割り当てられるメモリー・セグメントは、任意のスレッドから「アクセス済」にすることができます。

 MemorySegment segment = Arena.global().allocate(100, 1);
 ...
 // segment is never deallocated!

あるいは、クライアントは、ガベージ・コレクタによって自動的に管理される「境界有効期間」を特徴とするアリーナである「自動アリーナ」を取得できます。 自動アリーナのスコープは自動スコープです。 そのため、次に示すように、自動アリーナで割り当てられたメモリー・バッキング・メモリー・セグメントのリージョンは、自動アリーナ (およびそれによって割り当てられたすべてのセグメント)がunreachableになったあと、未指定の時間に解放されます:

 MemorySegment segment = Arena.ofAuto().allocate(100, 1);
 ...
 segment = null; // the segment region becomes available for deallocation after this point
自動アリーナで割り当てられたメモリー・セグメントは、任意のスレッドから「アクセス済」にすることもできます。

Javaランタイムの手元に割当て解除を残すのではなく、多くの場合、クライアントはメモリー・セグメントを戻すメモリーのリージョンに対する割当て解除のタイミングを制御することを希望します。 2種類のアリーナ、つまり「限定」およびsharedアリーナがサポートされています。 どちらも、手動で管理される期限付きライフ・タイムを備えています。 たとえば、限定されたアリーナが正常にclosedの場合、そのスコープは「無効」です。 その結果、アリーナによって割り当てられたすべてのメモリー・セグメントにアクセスできなくなり、そのメモリー・リージョンが割当て解除されます。

 MemorySegment segment = null;
 try (Arena arena = Arena.ofConfined()) {
     segment = arena.allocate(100);
     ...
 } // segment region deallocated here
 segment.get(ValueLayout.JAVA_BYTE, 0); // throws IllegalStateException
「限定アリーナ」で割り当てられたメモリー・セグメントには、アリーナを作成したスレッドのみが(クローズ済)にアクセスできます。 複数のスレッドからメモリー・セグメントへのアクセスが必要な場合、クライアントはかわりに「共有アリーナ」内のセグメントを割り当てることができます。

様々なアリーナの特性を次の表にまとめます:

Arenasの特徴
Kind 制限付き存続期間 明示的にクローズ可能 複数のスレッドからアクセス可能
グローバル No No Yes
自動 Yes No Yes
確定済 Yes Yes No
共有 Yes Yes Yes

安全性とスレッドの制約

Arenasは強力な時間的安全保証を提供: アリーナが割り当てたメモリー・セグメントには、そのアリーナを閉じたあとはアクセスできません。 この保証を提供するコストは、アリーナによって割り当てられたメモリー・セグメントにアクセスできるスレッドの数によって異なります。 たとえば、アリーナが常に1つのスレッドによって作成およびクローズされ、そのアリーナによって割り当てられたメモリー・セグメントに常に同じスレッドからアクセスされる場合は、正確さが微妙であることを確認します。

逆に、アリーナが複数のスレッドからアクセスできるセグメントを割り当てる場合や、アクセスしているスレッド以外のスレッドでアリーナをクローズできる場合は、正確さがはるかに複雑になります。 たとえば、アリーナに割り当てられているセグメントには、whileにもう一度アクセスして、アリーナを閉じようとします。 すべてのクライアント(単純なクライアントでも)パフォーマンスへの影響を発生させることなく、強力な時間的安全保証を提供するために、領域がthread-confined領域およびshared領域に分割されます。

限られた領域で、強力なスレッド制約の保証をサポートします。 作成時に、「所有者スレッド」に割り当てられるのは通常、作成操作を開始したスレッドです。 限定アリーナによって作成されたセグメントは、所有者スレッドによってのみ「アクセス済」になります。 さらに、所有者スレッド以外のスレッドから閉じ込められたアリーナを閉じようとすると、WrongThreadExceptionで失敗します。

一方、共有領域には所有者スレッドがありません。 共有アリーナによって作成されたセグメントは、どのスレッドでも「アクセス済」にできます。 これは、複数のスレッドが同じメモリー・セグメントに同時に(例:パラレル処理の場合)にアクセスする必要がある場合に役立ちます。 また、共有アリーナはどのスレッドでも閉じることができます。

カスタム・アリーナ

クライアントは、より効率的な割当て戦略を実装したり、アリーナをクローズできる(だれが)をより適切に制御するために、カスタム・アリーナを定義できます。 たとえば、次のコードでは、限定アリーナ(つまり、シングル・スレッド・アクセス)のように動作する「スライシング・アリーナ」を定義していますが、内部的には「スライシング・ロケータ」を使用して割当てリクエストに応答します。 スライス・アリーナが閉じられると、基礎となる限定されたアリーナも閉じられます。これにより、スライス・アリーナ(スライス・アリーナの範囲は基礎となる限定されたアリーナの範囲と同じであるため)に割り当てられているすべてのセグメントが無効になります:
class SlicingArena implements Arena {
    final Arena arena = Arena.ofConfined();
    final SegmentAllocator slicingAllocator;

    SlicingArena(long size) {
        slicingAllocator = SegmentAllocator.slicingAllocator(arena.allocate(size));
    }

    public MemorySegment allocate(long byteSize, long byteAlignment) {
        return slicingAllocator.allocate(byteSize, byteAlignment);
    }

    public MemorySegment.Scope scope() {
        return arena.scope();
    }

    public void close() {
        arena.close();
    }

}
つまり、スライス・アリーナは、非常に効率的でスケーラブルな割当て戦略を提供しながら、基礎となる限定されたアリーナによって提供されるタイムリな割当て解除保証を維持します:
try (Arena slicingArena = new SlicingArena(1000)) {
    for (int i = 0; i < 10; i++) {
        MemorySegment s = slicingArena.allocateFrom(JAVA_INT, 1, 2, 3, 4, 5);
        ...
    }
} // all memory allocated is released here
実装要件:
このインタフェースの実装はスレッド・セーフです。
導入されたバージョン:
22
関連項目:
  • メソッドの詳細

    • ofAuto

      static Arena ofAuto()
      ガベージ・コレクタによって自動的に管理される新しいアリーナを作成します。 戻されたアリーナで割り当てられるセグメントは、どのスレッドでも「アクセス済」になります。 戻されたアリーナでclose()をコールすると、UnsupportedOperationExceptionになります。

      戻されたアリーナによるメモリー・セグメント「割当済」は、ゼロで初期化されます。

      戻り値:
      ガベージ・コレクタによって自動的に管理される新しいアリーナ
    • global

      static Arena global()
      グローバル・アリーナを返します。 グローバル・アリーナで割り当てられるセグメントは、どのスレッドでも「アクセス済」にできます。 戻されたアリーナでclose()をコールすると、UnsupportedOperationExceptionになります。

      戻されたアリーナによるメモリー・セグメント「割当済」は、ゼロで初期化されます。

      戻り値:
      グローバル・アリーナ
    • ofConfined

      static Arena ofConfined()
      新しい限定されたアリーナを返します。 限定アリーナで割り当てられたセグメントは、アリーナの「所有者スレッド」というアリーナを作成したスレッドによって「アクセス済」になります。

      戻されたアリーナによるメモリー・セグメント「割当済」は、ゼロで初期化されます。

      戻り値:
      新しい限定アリーナ
    • ofShared

      static Arena ofShared()
      新しい共有領域を返します。 共有アリーナで割り当てられるセグメントは、どのスレッドでも「アクセス済」にできます。

      戻されたアリーナによるメモリー・セグメント「割当済」は、ゼロで初期化されます。

      戻り値:
      新しい共有アリーナ
    • allocate

      MemorySegment allocate(long byteSize, long byteAlignment)
      指定されたサイズ(バイト単位)および整列制約(バイト単位)のネイティブ・メモリー・セグメントを返します。 返されるセグメントは、この「アリーナ・スコープ」に関連付けられます。 セグメントのaddressは、セグメントをバッキングするメモリーの割当て済オフ・ヒープ・リージョンの開始アドレスであり、アドレスは指定された整列制約に従って整列されます。
      定義:
      インタフェースSegmentAllocator内のallocate
      実装要件:
      このメソッドの実装は、リクエストされたサイズを持つネイティブ・セグメントを返し、指定された整列制約と互換性がある必要があります。 さらに、このメソッドによって返される2つのセグメントS1, S2の場合、次の不変量を保持する必要があります:
          S1.asOverlappingSlice(S2).isEmpty() == true
      
      パラメータ:
      byteSize - ネイティブ・メモリー・セグメントをバックアップするメモリーのオフ・ヒープ・リージョンのサイズ(バイト単位)
      byteAlignment - ネイティブ・メモリー・セグメントをバックアップするメモリーのオフ・ヒープ・リージョンの整列制約(バイト単位)
      戻り値:
      新しいネイティブ・メモリー・セグメント
      例外:
      IllegalArgumentException - bytesSize < 0byteAlignment <= 0、またはbyteAlignmentが2の累乗でない場合
      IllegalStateException - このアリーナがすでにclosedである場合
      WrongThreadException - このアリーナが限定されていて、このメソッドがアリーナの所有者スレッド以外のスレッドから呼び出された場合
    • scope

      arenaスコープを返します。
      戻り値:
      arenaスコープ
    • close

      void close()
      このアリーナを閉じます。 このメソッドが正常に完了すると、アリーナ・スコープはaliveではなくなり、このメソッドに関連付けられているすべてのメモリー・セグメントにアクセスできなくなります。 さらに、このアリーナから取得したセグメントをバッキングするメモリーのオフ・ヒープ・リージョンもすべて解放されます。
      定義:
      close、インタフェースAutoCloseable
      APIのノート:
      この操作はべき等ではありません。つまり、すでに閉じているアリーナalwaysを閉じると、例外がスローされます。 これは意図的な設計の選択を反映しています: アリーナのクローズに失敗すると、基礎となるアプリケーション・ロジックにバグが表示される場合があります。
      実装要件:
      このメソッドが正常に完了した場合、this.scope().isAlive() == false 明示的なクローズ操作がサポートされていない場合は、実装でUnsupportedOperationExceptionをスローできます。
      例外:
      IllegalStateException - アリーナが既に閉鎖されている場合
      IllegalStateException - このアリーナに関連付けられたセグメントが同時にアクセスされる場合(downcall method handleRESTRICTEDなど)
      WrongThreadException - このアリーナが限定されていて、このメソッドがアリーナの所有者スレッド以外のスレッドから呼び出された場合
      UnsupportedOperationException - このアリーナを明示的に閉じられない場合
      RuntimeException - このアリーナ(例: MemorySegment.reinterpret(long, Arena, Consumer)RESTRICTEDまたはMemorySegment.reinterpret(Arena, Consumer)RESTRICTEDをコールした結果)に関連付けられたカスタム・クリーンアップ・アクションの実行中に例外がスローされた場合。
      関連項目: