public final class MemoryHandles extends Object
varHandle(Class, ByteOrder)、varHandle(Class, long, ByteOrder)を参照してください。)のいずれかから起動する必要があります。 これにより、変数の型(すべてのプリミティブ・タイプをサポートしますが、voidとbooleanもサポートされます。)に加え、配置制約、およびメモリー・アクセスvarハンドルに関連付けられたバイト順を決定します。 結果として得られるメモリー・アクセス変数ハンドルを様々な方法で組み合せて、別のアドレス指定モードをエミュレートできます。 このクラス機能で作成されるvarハンドルは、「必須」座標型(タイプMemoryAddress)と、マルチディメンション配列の索引付けをエミュレートするために使用できる0個以上のlong座標型です。
たとえば、次のように構築されたSequenceLayoutインスタンスで表されるメモリー・レイアウトを考えます:
SequenceLayout seq = MemoryLayout.ofSequence(5, MemoryLayout.ofStruct( MemoryLayout.ofPaddingBits(32), MemoryLayout.ofValueBits(32, ByteOrder.BIG_ENDIAN).withName("value") ));
valueという名前のメンバーのレイアウトにアクセスするには、次のようにしてmemory access varハンドルを構築できます:
VarHandle handle = MemoryHandles.varHandle(int.class, ByteOrder.BIG_ENDIAN); //(MemoryAddress) -> int handle = MemoryHandles.withOffset(handle, 4); //(MemoryAddress) -> int handle = MemoryHandles.withStride(handle, 8); //(MemoryAddress, long) -> int
アドレス指定モード
メモリー・アクセス変数ハンドルがアクセスする最終的なメモリーのロケーションは、次のように計算できます:ここで、address = base + offset
baseはMemoryAddressアクセス座標で表されるアドレスを表し、offsetは次の形式で表現できます:
ここでoffset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
x_1、x_2、... x_nは、オプションのlongアクセス座標として提供される「動的」値であり、一方、c_1、c_2、... c_m、s_0、s_1、... s_nはstatic定数で、withOffset(VarHandle, long)およびwithStride(VarHandle, long)コンビナータを通じて取得できます。
配置モードとアクセス・モード
メモリー・アクセス・メトリックのハンドルは、アクセス・サイズのSおよび整列制約のB (両方ともバイトで表します)に関連付けられています。 メモリー・アクセス操作が、位置合せ制約SとBの両方と互換性のあるメモリー・アドレスAで発生する場合、「完全に整列」であるとします。 アクセスが完全に整列されている場合、次のアクセス・モードがサポートされ、原子性アクセスをサポートする保証があります:
- 32ビット・プラットフォーム上の
longおよびdoubleのアクセス・モードgetおよびsetを除き、すべてのTの読み取り/書き込みアクセス・モード。 int、long、floatまたはdoubleのアトミック更新アクセス・モード。 (JDKの今後の主要なプラットフォーム・リリースは、現在サポートされていない特定のアクセス・モードに対して追加の型をサポートする可能性があります。)intおよびlongの数値アトミック更新アクセス・モード。 (JDKの将来の主要なプラットフォーム・リリースは、現在サポートされていない特定のアクセス・モードに対して、追加の数値型をサポートする可能性があります。)intとlongのビット単位アトミック更新アクセス・モード。 (JDKの将来の主要なプラットフォーム・リリースは、現在サポートされていない特定のアクセス・モードに対して、追加の数値型をサポートする可能性があります。)
Tがfloatまたはdoubleの場合、アトミック更新アクセス・モードでは、ビット単位表現(それぞれFloat.floatToRawIntBits(float)とDouble.doubleToRawLongBits(double)を参照してください)を使用して値が比較されます。
あるいは、メモリー・アクセス操作が、位置情報制約Bとのみ互換性のあるメモリー・アドレスAで発生する場合、「部分的に整列」です。その場合、getおよびsetアクセス・モード以外でアクセスするとIllegalStateExceptionになります。 アクセスが部分的に整列されている場合、アトミック・アクセスは、AおよびSのGCDを分割する2の最大電力に関してのみ保証されます。
最後に、他のすべてのケースでは、メモリー・アクセス操作は「右揃え」であると言っています; この場合、使用するアクセス・モードに関係なくIllegalStateExceptionがスローされます。
-
メソッドのサマリー
修飾子と型 メソッド 説明 static VarHandleasAddressVarHandle(VarHandle target)既存のvarハンドルを、キャリア・タイプがMemoryAddressの新しいvarハンドルに適応させます。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(Class<?> carrier, long alignmentBytes, ByteOrder byteOrder)指定されたキャリア・タイプ、位置合せ制約、およびバイト順序でメモリー・アクセス・メトリックを作成します。static VarHandlevarHandle(Class<?> carrier, ByteOrder byteOrder)指定されたキャリア・タイプとバイト順序でメモリー・アクセス・メトリックを作成します。static VarHandlewithOffset(VarHandle target, long bytesOffset)fixedオフセットを受信MemoryAddress座標に追加し、その値をターゲットvarハンドルに伝播するvarハンドルを返します。static VarHandlewithStride(VarHandle target, long bytesStride)受信するMemoryAddressアクセス座標値にvariableオフセットを追加し、その値をターゲットのvarハンドルに伝播するvarハンドルを返します。
-
メソッドの詳細
-
varHandle
指定されたキャリア・タイプとバイト順序でメモリー・アクセス・メトリックを作成します。 結果としてのメモリー・アクセス変数ハンドルには、MemoryAddressアクセス座標が1つあり、変数の型は指定されたキャリアの型によって設定されます。 生成されるメモリー・アクセス変数ハンドルの位置合せ制約は、キャリア・タイプのメモリー内サイズと同じで、アクセスされたオフセットは0(ゼロ)に設定されます。- APIのノート:
- 結果の変数ハンドルは、すべてのメモリー・アクセス変数ハンドルに共通な、「アクセス・モード制限」の特定の機能を備えています。
- パラメータ:
carrier- キャリア・タイプ。 有効なキャリアは、byte、short、char、int、float、longおよびdoubleです。byteOrder- 必要なバイト順。- 戻り値:
- 新しいメモリー・アクセス・メトリックのハンドル。
- 例外:
IllegalArgumentException- 不正なキャリア・タイプが使用されている場合
-
varHandle
指定されたキャリア・タイプ、位置合せ制約、およびバイト順序でメモリー・アクセス・メトリックを作成します。 結果としてのメモリー・アクセス変数ハンドルには、MemoryAddressアクセス座標が1つあり、変数の型は指定されたキャリアの型によって設定されます。 アクセスされたオフセットはゼロです。- APIのノート:
- 結果の変数ハンドルは、すべてのメモリー・アクセス変数ハンドルに共通な、「アクセス・モード制限」の特定の機能を備えています。
- パラメータ:
carrier- キャリア・タイプ。 有効なキャリアは、byte、short、char、int、float、longおよびdoubleです。alignmentBytes- 位置合せ制約(バイト単位)です。 2の累乗である必要があります。byteOrder- 必要なバイト順。- 戻り値:
- 新しいメモリー・アクセス・メトリックのハンドル。
- 例外:
IllegalArgumentException- 不正なキャリア・タイプが使用されている場合、またはalignmentBytesが2の累乗でない場合。
-
withOffset
fixedオフセットを受信MemoryAddress座標に追加し、その値をターゲットvarハンドルに伝播するvarハンドルを返します。 つまり、戻されたvarハンドルがオフセットOのメモリー・ロケーションを指すメモリー・アドレス座標を受け取ると、オフセットO' + Oのメモリー・ロケーションを指すメモリー・アドレス座標が作成され、ターゲットvarハンドルに渡されます。 返されるvarハンドルは、ターゲットのvarハンドルと同じ型およびアクセス座標を特徴とします。- パラメータ:
target- オフセット調整後にアクセスするターゲット・メモリー・アクセス・ハンドルです。bytesOffset- オフセット(バイト)。 正またはゼロである必要があります。- 戻り値:
- 適応されたvarハンドル。
- 例外:
IllegalArgumentException- 最初のアクセス座標型がMemoryAddress型でない場合。
-
withStride
受信するMemoryAddressアクセス座標値にvariableオフセットを追加し、その値をターゲットのvarハンドルに伝播するvarハンドルを返します。 つまり、返されるvarハンドルがオフセットOのメモリー・ロケーションを指すメモリー・アドレス座標を受け取ると、オフセット(S * X) + Oが作成され、ターゲットvarハンドルに渡されます。Sは定数「ストライド」ですが、Xは追加のアクセス座標(型longの)として提供される動的値です。 返されるvarハンドルは、ターゲットvarハンドルと同じ型を特徴とします。long型の追加のアクセス座標が、ターゲットvarハンドルのアクセス座標型の、MemoryAddress型の先行アクセス座標の直後の位置に追加されます。- パラメータ:
target- スケール調整後にアクセスするターゲット・メモリー・アクセス・ハンドルです。bytesStride- 座標値を乗算する取消し線(バイト単位)。- 戻り値:
- 適応されたvarハンドル。
- 例外:
IllegalArgumentException- 最初のアクセス座標型がMemoryAddress型でない場合。
-
asAddressVarHandle
既存のvarハンドルを、キャリア・タイプがMemoryAddressの新しいvarハンドルに適応させます。 つまり、戻されたvarハンドルでVarHandle.get(Object...)をコールすると、読取り数値がメモリー・アドレス(MemoryAddress.ofLong(long)をコールする場合と同様)に変換されます。同様に、VarHandle.set(Object...)をコールすると、設定するメモリー・アドレスが数値に変換され、メモリーに書き込まれます。 (職責:至)メモリーから(resp.書込み)を読み取るバイト数は、元のメモリー・アクセス変数ハンドルのキャリアによって異なります。- パラメータ:
target- 適応させるメモリー・アクセス変数ハンドル- 戻り値:
- 適応されたvarハンドル。
- 例外:
IllegalArgumentException-varHandleのキャリア・タイプがboolean、floatまたはdoubleのいずれかであるか、プリミティブ・タイプでない場合。
-
asUnsigned
受信値を絞り込み、指定された型との間で送信値を広げることで、ターゲット変数ハンドルを適応させます。返されたvarハンドルを使用すると、符号なしプリミティブ・データ型を、より広範囲の符号付きプリミティブ・タイプであるかのように簡単に扱うことができます。 たとえば、unsigned shortをJava
intとしてモデル化して、負の値を処理しないようにすると便利な場合があります。これは、Javashortとしてモデル化されている場合です。 これは次の例で説明します。MemorySegment segment = MemorySegment.allocateNative(2); VarHandle SHORT_VH = MemoryLayouts.JAVA_SHORT.varHandle(short.class); VarHandle INT_VH = MemoryHandles.asUnsigned(SHORT_VH, int.class); SHORT_VH.set(segment.baseAddress(), (short)-1); INT_VH.get(segment.baseAddress()); // returns 65535たとえば、結果のvarハンドルで
VarHandle.set(Object...)をコールすると、受信値(型adaptedTypeの)が「プリミティブ変換を狭める」によって変換され、targetvarハンドルに渡されます。 ナロー・プリミティブ・コンバージョンでは、数値の全体的な大きさに関する情報が失われる場合があります。 逆に、結果のvarハンドルでVarHandle.get(Object...)などをコールすると、targetvarハンドルから取得された戻り値は、コール元に戻される前に「符号なしワイドニング変換」によって変換されます。 符号なしワイド変換では、targetキャリア・タイプより大きい上位ビットはゼロで、下位ビットの(targetキャリア・タイプの幅と等しい)はtargetvarハンドルから取得した値のビットと等しくなります。返されるvarハンドルは、変数の型
adaptedType、同じアクセス座標、同じアクセス・モード(targetvarハンドルで機能するものと同じアトミック・アクセス保証を備えています(VarHandle.AccessModeおよび同じアトミック・アクセス保証を参照)。- パラメータ:
target- 適応させるメモリー・アクセス変数ハンドルadaptedType- 適応型- 戻り値:
- 適応されたvarハンドル。
- 例外:
IllegalArgumentException-targetのキャリア・タイプがbyte、shortまたはintのいずれでもない場合、adaptedTypeがintまたはlongのビット幅より大きい場合、adaptedTypeのビット幅がtargetキャリア・タイプのビット幅より大きい場合NullPointerException-targetまたはadaptedTypeのいずれかがnullの場合- 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ハンドルは、ターゲットのvarハンドルで機能するアクセス・モードと同じアクセス・モードを備えています(
VarHandle.AccessModeおよびアトミック・アクセス保証を参照)。- パラメータ:
target- ターゲット変数ハンドルfilterToTarget- 一部のタイプのSをtargetのタイプに変換するフィルタfilterFromTarget-targetのタイプをSのタイプに変換するフィルタ- 戻り値:
- 指定されたボクシング/アン・ボクシング変換を実行して、新しい型を受け入れるアダプタ変数ハンドル。
- 例外:
NullPointerException-target、filterToTargetまたはfilterFromTargetが== nullの場合。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ハンドルには、ターゲットのvarハンドルの機能と同じアクセス・モードである(
VarHandle.AccessModeを参照してください)およびアトミック・アクセスが保証されます。- パラメータ:
target- ターゲット変数ハンドルpos- 変換する最初の座標の位置filters- 位置posから座標を変換するために使用される単項関数- 戻り値:
- 指定された変換を新しい座標値に適用して、新しい座標型を受け入れるアダプタ変数ハンドル。
- 例外:
NullPointerException- いずれかのtargetの場合、filtersは== nullです。IllegalArgumentException-filtersのハンドルが整形式でない場合、つまりS1 -> T1, S2 -> T2, ... Sn -> Tn以外のタイプを持つ場合、T1, T2 ... Tnは、ターゲットvarハンドルの位置posで始まる座標タイプであり、posが0とターゲットvarハンドル座標引数の間にない場合、または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ハンドル
- 例外:
NullPointerException- いずれかのtargetの場合、valuesは== nullです。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ハンドルを提供します。指定された配列によって並べ替えが制御されます。
#Iに着信座標の数(値はnewCoordinates.size())をコールし、#Oに送信座標の数(ターゲット変数ハンドルに関連付けられた座標の数)をコールします。 このとき、並べ替え配列の長さは#O、各要素は#Iより小さい負でない数でなければいけません。#O未満のすべてのNについて、N番目の送信座標は、Iがreorder[N]であるI番目の受信座標から取得されます。座標値の変換は適用されません。
newCoordinatesによって決定される各受信座標の型は、ターゲット変数ハンドル内の対応する送信座標の型と同じである必要があります。並べ替え配列では、実際の入れ替えを指定する必要はありません。 入力座標は、そのインデックスが配列内に複数回出現する場合は複製され、インデックスが配列内に存在しない場合は入力座標が削除されます。
結果のvarハンドルには、ターゲットのvarハンドルの機能と同じアクセス・モードである(
VarHandle.AccessModeを参照してください)およびアトミック・アクセスが保証されます。- パラメータ:
target- 座標が並べ替えられた後に呼び出すvarハンドルnewCoordinates- 新しい座標型reorder- 並べ替えを制御するインデックス配列- 戻り値:
- ターゲットのvarハンドルを呼び出す前に、着信座標値を再配置するアダプタのvarハンドル
- 例外:
NullPointerException-target、newCoordinatesまたはreorderが== nullの場合。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ハンドルには、ターゲットのvarハンドルの機能と同じアクセス・モードである(
VarHandle.AccessModeを参照してください)およびアトミック・アクセスが保証されます。- パラメータ:
target- 座標がフィルタ処理された後に呼び出すvarハンドルpos- フィルタ処理される座標の位置filter- フィルタ・メソッド・ハンドル- 戻り値:
- ターゲットのvarハンドルを呼び出す前に、着信座標値をフィルタ処理するアダプタのvarハンドル
- 例外:
NullPointerException- いずれかのtargetの場合、filterは== nullです。IllegalArgumentException-filterの戻り型がvoidの場合、またはターゲットのvarハンドルの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ハンドル
- 例外:
NullPointerException- いずれかのtargetの場合、valueTypesは== nullです。IllegalArgumentException-posが0からターゲットのvarハンドル座標引数(両端を含む)の間にない場合。
-