varHandle(ValueLayout)を使用して取得できます。 指定された値のレイアウトによって、タイプ、および位置合わせ制約、およびメモリー・アクセス変数ハンドルに関連付けられたバイト順序が決まります。
結果として得られるメモリー・アクセス変数ハンドルを様々な方法で組み合せて、別のアドレス指定モードをエミュレートできます。 このクラスによって作成されるvarハンドルは、「必須」座標型(タイプMemorySegmentの)と、間接参照が発生するセグメントに対するオフセット(バイト単位)を表すlong座標型を特徴とします。
たとえば、次のように構築されたGroupLayoutインスタンスで表されるメモリー・レイアウトを考えます:
GroupLayout seq = MemoryLayout.structLayout(
MemoryLayout.paddingLayout(32),
ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withName("value")
);
valueという名前のメンバーのレイアウトにアクセスするには、次のようにしてmemory access varハンドルを構築できます:
VarHandle handle = MemoryHandles.varHandle(ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN)); //(MemorySegment, long) -> int
handle = MemoryHandles.insertCoordinates(handle, 1, 4); //(MemorySegment) -> int
特に指定がないかぎり、null引数、またはこのクラスのメソッドに1つ以上のnull要素を含む配列引数を渡すと、NullPointerExceptionがスローされます。
配置モードとアクセス・モード
メモリー・アクセス・メトリックのハンドルは、アクセス・サイズのSおよび整列制約のB (両方ともバイトで表します)に関連付けられています。 メモリー・アクセス操作が、位置合せ制約SとBの両方と互換性のあるメモリー・アドレスAで発生する場合、「完全に整列」であるとします。 アクセスが完全に整列されている場合、次のアクセス・モードがサポートされ、原子性アクセスをサポートする保証があります:
- 32ビット・プラットフォーム上の
longおよびdoubleのアクセス・モードgetおよびsetを除き、すべてのTの読み取り/書き込みアクセス・モード。 int,long,float,doubleまたはMemoryAddressのアトミック更新アクセス・モード。 (JDKの今後の主要なプラットフォーム・リリースは、現在サポートされていない特定のアクセス・モードに対して追加の型をサポートする可能性があります。)int、longおよびMemoryAddressの数値アトミック更新アクセス・モード。 (JDKの将来の主要なプラットフォーム・リリースは、現在サポートされていない特定のアクセス・モードに対して、追加の数値型をサポートする可能性があります。)int、longおよびMemoryAddressのビット単位のアトミック更新アクセス・モード。 (JDKの将来の主要なプラットフォーム・リリースは、現在サポートされていない特定のアクセス・モードに対して、追加の数値型をサポートする可能性があります。)
Tがfloat、doubleまたはMemoryAddressの場合、アトミック更新アクセス・モードは、ビット単位の表現(Float.floatToRawIntBits(float)、Double.doubleToRawLongBits(double)およびMemoryAddress.toRawLongValue()をそれぞれ参照してください)を使用して値を比較します。
あるいは、メモリー・アクセス操作が、位置情報制約Bとのみ互換性のあるメモリー・アドレスAで発生する場合、「部分的に整列」です。その場合、getおよびsetアクセス・モード以外でアクセスするとIllegalStateExceptionになります。 アクセスが部分的に整列されている場合、アトミック・アクセスは、AおよびSのGCDを分割する2の最大電力に関してのみ保証されます。
最後に、他のすべてのケースでは、メモリー・アクセス操作は「右揃え」であると言っています; この場合、使用するアクセス・モードに関係なくIllegalStateExceptionがスローされます。
-
メソッドのサマリー
修飾子と型メソッド説明static VarHandleasUnsigned(VarHandle target, Class<?> adaptedType) 受信値を絞り込み、指定された型との間で送信値を広げることで、ターゲット変数ハンドルを適応させます。static VarHandlecollectCoordinates(VarHandle target, int pos, MethodHandle filter) フィルタ(メソッド・ハンドル)を使用して座標値のサブ・シーケンスを前処理することで、ターゲット変数ハンドルを調整します。static VarHandledropCoordinates(VarHandle target, int pos, Class<?>... valueTypes) ターゲットのvarハンドルに委譲する前にダミー座標を破棄するvarハンドルを返します。static VarHandlefilterCoordinates(VarHandle target, int pos, MethodHandle... filters) 単項フィルタ関数を使用して着信座標値を前処理することで、ターゲット変数ハンドルを適応させます。static VarHandlefilterValue(VarHandle target, MethodHandle filterToTarget, MethodHandle filterFromTarget) フィルタ関数のペアを使用して受信値と送信値を事前処理することで、ターゲット変数ハンドルを適応させます。static VarHandleinsertCoordinates(VarHandle target, int pos, Object... values) Varハンドル呼出しの前に、1つ以上の「バインド座標」を持つターゲットvarハンドルを提供します。static VarHandlepermuteCoordinates(VarHandle target, List<Class<?>> newCoordinates, int... reorder) 新しい座標が指定された座標と一致するように再配列することで、ターゲットのvarハンドルの座標値を適応させるvarハンドルを提供します。static VarHandlevarHandle(ValueLayout layout) 指定された値レイアウトからメモリー・アクセス変数ハンドルを作成します。
-
メソッドの詳細
-
varHandle
public static VarHandle varHandle(ValueLayout layout) 指定された値レイアウトからメモリー・アクセス変数ハンドルを作成します。 指定されたレイアウトでは、返されるvarハンドルに関連付けられた「キャリア・タイプ」、「バイト・サイズ」、「バイト配置」および「バイト・オーダー」を指定します。 戻されるvarハンドル・タイプはcarrierで、座標タイプのリストは(MemorySegment, long)です。long座標タイプは、指定されたメモリー・セグメントへのバイト・オフセットに対応します。 戻されたvarハンドルは、指定されたメモリー・セグメント内のオフセットにあるバイトにアクセスし、指定されたendiannessに従ってcarrier型の値との間でバイトを構成します。結果として得られるメモリー・アクセスvarハンドルの位置合せ制約(バイト単位)は、alignmentBytesによって指定されます。- APIのノート:
- 結果の変数ハンドルは、すべてのメモリー・アクセス変数ハンドルに共通な、「アクセス・モード制限」の特定の機能を備えています。
- パラメータ:
layout- メモリー・アクセス・ハンドルを取得する値レイアウト。- 戻り値:
- 新しいメモリー・アクセス・メトリックのハンドル。
- 例外:
IllegalArgumentException- 不正なキャリア・タイプが使用されている場合、またはalignmentBytesが2の累乗でない場合。
-
asUnsigned
受信値を絞り込み、指定された型との間で送信値を広げることで、ターゲット変数ハンドルを適応させます。返されたvarハンドルを使用すると、符号なしプリミティブ・データ型を、より広範囲の符号付きプリミティブ・タイプであるかのように簡単に扱うことができます。 たとえば、unsigned shortをJava
intとしてモデル化して、負の値を処理しないようにすると便利な場合があります。これは、Javashortとしてモデル化されている場合です。 これは次の例で説明します。MemorySegment segment = MemorySegment.allocateNative(2, ResourceScope.newImplicitScope()); VarHandle SHORT_VH = ValueLayout.JAVA_SHORT.varHandle(); VarHandle INT_VH = MemoryHandles.asUnsigned(SHORT_VH, int.class); SHORT_VH.set(segment, (short)-1); INT_VH.get(segment); // returns 65535たとえば、結果のvarハンドルで
VarHandle.set(Object...)をコールすると、受信値(型adaptedTypeの)が「プリミティブ変換を狭める」によって変換され、targetvarハンドルに渡されます。 ナロー・プリミティブ・コンバージョンでは、数値の全体的な大きさに関する情報が失われる場合があります。 逆に、結果のvarハンドルでVarHandle.get(Object...)などをコールすると、targetvarハンドルから取得された戻り値は、コール元に戻される前に「符号なしワイドニング変換」によって変換されます。 符号なしワイド変換では、targetキャリア・タイプより大きい上位ビットはゼロで、下位ビットの(targetキャリア・タイプの幅と等しい)はtargetvarハンドルから取得した値のビットと等しくなります。戻されるvarハンドルには、変数タイプ
adaptedTypeと、同じアクセス座標、同じアクセス・モード(VarHandle.AccessModeを参照してください)、およびtargetのvarハンドルによって示されるものと同じアトミック・アクセスが保証されます。- パラメータ:
target- 適応させるメモリー・アクセス変数ハンドルadaptedType- 適応型- 戻り値:
- 適応されたvarハンドル。
- 例外:
IllegalArgumentException-targetのキャリア・タイプがbyte、shortまたはintのいずれでもない場合。adaptedTypeがintまたはlongのいずれかでない場合。adaptedTypeのビット幅がtargetキャリア・タイプのビット幅よりも大きくない場合。- Java言語仕様を参照してください:
-
5.1.3 プリミティブ・コンバージョンの解説
-
filterValue
public static VarHandle filterValue(VarHandle target, MethodHandle filterToTarget, MethodHandle filterFromTarget) フィルタ関数のペアを使用して受信値と送信値を事前処理することで、ターゲット変数ハンドルを適応させます。たとえば、結果のvarハンドルで
VarHandle.set(Object...)をコールすると、最初のフィルタを使用して受信値(Tタイプ。Tは最初のフィルタ関数のlastパラメータ・タイプです。)が処理され、ターゲットのvarハンドルに渡されます。 逆に、結果のvarハンドルでVarHandle.get(Object...)などをコールすると、ターゲットのvarハンドル(Tタイプ。Tは、2番目のフィルタ関数のlastパラメータ・タイプです。)から取得された戻り値は、2番目のフィルタを使用して処理され、コール元に戻されます。VarHandle.AccessMode.COMPARE_AND_EXCHANGEなどのより高度なアクセス・モード・タイプでは、両方のフィルタが同時に適用される場合があります。ボクシング・フィルタおよびアンボックス・フィルタを整形式にするには、それぞれ
(A... , S) -> Tおよび(A... , T) -> Sの形式にする必要があります(Tはターゲット変数ハンドルのタイプです)。 この場合、結果のvarハンドルはS型になり、追加の座標A...(ターゲット変数ハンドルの座標に追加されます。)を特徴とします。ボクシング・フィルタおよびアンボックス化フィルタが呼び出されたときにチェック例外をスローすると、結果のvarハンドルは
IllegalStateExceptionをスローします。結果のvarハンドルには、ターゲットのvarハンドルの機能と同じアクセス・モードである(
VarHandle.AccessModeを参照してください)およびアトミック・アクセスが保証されます。- パラメータ:
target- ターゲット変数ハンドルfilterToTarget- 一部のタイプのSをtargetのタイプに変換するフィルタfilterFromTarget-targetのタイプをSのタイプに変換するフィルタ- 戻り値:
- 指定されたボクシング/アン・ボクシング変換を実行して、新しい型を受け入れるアダプタ変数ハンドル。
- 例外:
IllegalArgumentException-filterFromTargetおよびfilterToTargetの形式が適切でない場合、つまり、それぞれ(A... , S) -> Tおよび(A... , T) -> S以外の型があり、Tはターゲット変数ハンドルのタイプであるか、filterFromTargetまたはfilterToTargetのいずれかがチェックされた例外をスローすると判断された場合。
-
filterCoordinates
public static VarHandle filterCoordinates(VarHandle target, int pos, MethodHandle... filters) 単項フィルタ関数を使用して着信座標値を前処理することで、ターゲット変数ハンドルを適応させます。たとえば、結果のvarハンドルで
VarHandle.get(Object...)をコールすると、pos(C1, C2 ... Cn型。C1, C2 ... Cnは単項フィルタ関数の戻り型です。)の位置から始まる着信座標値が新しい値(S1, S2 ... Sn型。S1, S2 ... Snは単項フィルタ関数のパラメータ型です。)に変換され、(適応によって変更されていない座標とともに)がターゲットのvarハンドルに渡されます。座標フィルタを整形式にするには、
S1 -> T1, S2 -> T1 ... Sn -> Tnの形式にする必要があります。T1, T2 ... Tnは、ターゲット変数ハンドルの位置posから始まる座標タイプです。いずれかのフィルタが呼び出されたときにチェック例外をスローした場合、結果のvarハンドルは
IllegalStateExceptionをスローします。結果のvarハンドルには、ターゲットのvarハンドルの機能と同じアクセス・モードである(
VarHandle.AccessModeを参照してください)およびアトミック・アクセスが保証されます。- パラメータ:
target- ターゲット変数ハンドルpos- 変換する最初の座標の位置filters- 位置posから座標を変換するために使用される単項関数- 戻り値:
- 指定された変換を新しい座標値に適用して、新しい座標型を受け入れるアダプタ変数ハンドル。
- 例外:
IllegalArgumentException-filtersのハンドルが整形式でない場合、つまり、S1 -> T1, S2 -> T2, ... Sn -> Tn以外のタイプがあり、posが0の間でない場合は、T1, T2 ... Tnはターゲット変数ハンドルの位置posから始まる座標タイプです。また、ターゲット変数ハンドルの座標アリティ(包含)や、posから始まる実際の座標タイプ数よりも多くのフィルタが指定されている場合、またはいずれかのフィルタがチェックされた例外をスローすることを決定した場合。
-
insertCoordinates
Varハンドル呼出しの前に、1つ以上の「バインド座標」を持つターゲットvarハンドルを提供します。 その結果、結果のvarハンドルは、ターゲットのvarハンドルよりも座標型が少なくなります。たとえば、結果のvarハンドルで
VarHandle.get(Object...)をコールすると、着信座標値がバインドされた座標値と結合され、ターゲットのvarハンドルに渡されます。境界座標を整形するには、その型は
T1, T2 ... Tnである必要があります。T1, T2 ... Tnは、ターゲット変数ハンドルの位置posから始まる座標タイプです。結果のvarハンドルには、ターゲットのvarハンドルの機能と同じアクセス・モードである(
VarHandle.AccessModeを参照してください)およびアトミック・アクセスが保証されます。- パラメータ:
target- バインドされた座標が挿入された後に呼び出すvarハンドルpos- 挿入する最初の座標の位置values- 挿入する一連のバウンド座標- 戻り値:
- ターゲットのvarハンドルを呼び出す前に、追加の座標を挿入するアダプタのvarハンドル
- 例外:
IllegalArgumentException-posが0からターゲットのvarハンドル座標引数(両端を含む)の間にない場合、またはposから使用可能な座標タイプの実際の数よりも多くの値が指定されている場合。ClassCastException-valuesのバインドされた座標が整形式でない場合、つまり、T1, T2 ... Tn以外の型を持つ場合(T1, T2 ... Tnはターゲット変数ハンドルのposの位置から始まる座標型です)。
-
permuteCoordinates
public static VarHandle permuteCoordinates(VarHandle target, List<Class<?>> newCoordinates, int... reorder) 新しい座標が指定された座標と一致するように再配列することで、ターゲットのvarハンドルの座標値を適応させるvarハンドルを提供します。指定された配列によって並べ替えが制御されます。 着信座標数(値
newCoordinates.size())を#Iにコールし、発信座標数(ターゲット変数ハンドルに関連付けられた座標の数)を#Oにコールします。 このとき、並べ替え配列の長さは#O、各要素は#Iより小さい負でない数でなければいけません。#O未満のすべてのNについて、N番目の送信座標は、Iがreorder[N]であるI番目の受信座標から取得されます。座標値の変換は適用されません。
newCoordinatesによって決定される各受信座標の型は、ターゲット変数ハンドル内の対応する送信座標の型と同じである必要があります。並べ替え配列では、実際の入れ替えを指定する必要はありません。 入力座標は、そのインデックスが配列内に複数回出現する場合は複製され、インデックスが配列内に存在しない場合は入力座標が削除されます。
結果のvarハンドルには、ターゲットのvarハンドルの機能と同じアクセス・モードである(
VarHandle.AccessModeを参照してください)およびアトミック・アクセスが保証されます。- パラメータ:
target- 座標が並べ替えられた後に呼び出すvarハンドルnewCoordinates- 新しい座標型reorder- 並べ替えを制御するインデックス配列- 戻り値:
- ターゲットのvarハンドルを呼び出す前に、着信座標値を再配置するアダプタのvarハンドル
- 例外:
IllegalArgumentException- 索引配列の長さがターゲットのvarハンドルの座標数と等しくない場合、索引配列要素がnewCoordinatesの座標に対して有効な索引でない場合、またはターゲットのvarハンドルとnewCoordinatesの対応する座標タイプが同じでない場合。
-
collectCoordinates
public static VarHandle collectCoordinates(VarHandle target, int pos, MethodHandle filter) フィルタ(メソッド・ハンドル)を使用して座標値のサブ・シーケンスを前処理することで、ターゲット変数ハンドルを調整します。 前処理された座標はフィルタ関数の結果(もしあれば)に置き換えられ、変更された(通常は短縮)座標リストでターゲット変数ハンドルが呼び出されます。Rがフィルタ(voidにはできません)の戻り型である場合、ターゲット変数ハンドルは、posの位置の座標として、フィルタに渡されない座標の前または後ろ(あるいはその両方)にR型の値を受け入れる必要があります。 座標の順序は変更されず、フィルタから返される結果は、最初にアダプタに渡された座標のサブ・シーケンス全体を(順番)に置き換えます。フィルタの引数の型(もしあれば)は、調整後のvarハンドルの位置
posにあるターゲットvarハンドルのゼロまたは1つの座標型を置き換えます。 フィルタの戻り型は、posの位置にあるターゲット変数ハンドルの座標型と同じである必要があり、そのターゲット変数ハンドル座標はフィルタの戻り値によって提供されます。いずれかのフィルタが呼び出されたときにチェック例外をスローした場合、結果のvarハンドルは
IllegalStateExceptionをスローします。結果のvarハンドルには、ターゲットのvarハンドルの機能と同じアクセス・モードである(
VarHandle.AccessModeを参照してください)およびアトミック・アクセスが保証されます。- パラメータ:
target- 座標がフィルタ処理された後に呼び出すvarハンドルpos- フィルタ処理される座標の位置filter- フィルタ・メソッド・ハンドル- 戻り値:
- ターゲットのvarハンドルを呼び出す前に、着信座標値をフィルタ処理するアダプタのvarハンドル
- 例外:
IllegalArgumentException-filterの戻り型が無効である場合、またはターゲット変数ハンドルのpos座標と同じではない場合、posが0からターゲットのvarハンドルの座標アリティの間にない場合(結果として得られるvarハンドル・タイプが「座標が多すぎます」の場合、またはfilterによってチェックされた例外がスローされることが判明している場合)。
-
dropCoordinates
ターゲットのvarハンドルに委譲する前にダミー座標を破棄するvarハンドルを返します。 その結果、結果のvarハンドルは、ターゲットのvarハンドルよりも座標型が多くなります。pos引数の範囲はゼロからNです。ここで、Nはターゲットのvarハンドル座標型の引数です。posがゼロの場合、ダミー座標はターゲットの実引数の前に配置され、posがNの場合は後ろに配置されます。結果のvarハンドルには、ターゲットのvarハンドルの機能と同じアクセス・モードである(
VarHandle.AccessModeを参照してください)およびアトミック・アクセスが保証されます。- パラメータ:
target- ダミー座標がドロップされた後に呼び出すvarハンドルpos- (左端のゼロ)を削除する最初の座標の位置valueTypes- ドロップする座標の型- 戻り値:
- ターゲットvarハンドルを呼び出す前にダミー座標をドロップするアダプタvarハンドル
- 例外:
IllegalArgumentException-posが0からターゲットのvarハンドル座標引数(両端を含む)の間にない場合。
-