Class MemoryHandles

java.lang.Object
jdk.incubator.foreign.MemoryHandles

public final class MemoryHandles
extends Object
This class defines several factory methods for constructing and combining memory access var handles. To obtain a memory access var handle, clients must start from one of the leaf methods (see varHandle(Class, ByteOrder), varHandle(Class, long, ByteOrder)). This determines the variable type (all primitive types but void and boolean are supported), as well as the alignment constraint and the byte order associated to a memory access var handle. The resulting memory access var handle can then be combined in various ways to emulate different addressing modes. The var handles created by this class feature a mandatory coordinate type (of type MemoryAddress), and zero or more long coordinate types, which can be used to emulate multi-dimensional array indexing.

As an example, consider the memory layout expressed by a SequenceLayout instance constructed as follows:


SequenceLayout seq = MemoryLayout.ofSequence(5,
    MemoryLayout.ofStruct(
        MemoryLayout.ofPaddingBits(32),
        MemoryLayout.ofValueBits(32, ByteOrder.BIG_ENDIAN).withName("value")
    ));
 
To access the member layout named value, we can construct a memory access var handle as follows:

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
 

Addressing mode

The final memory location accessed by a memory access var handle can be computed as follows:

address = base + offset
 
where base denotes the address expressed by the MemoryAddress access coordinate, and offset can be expressed in the following form:

offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
 
where x_1, x_2, ... x_n are dynamic values provided as optional long access coordinates, whereas c_1, c_2, ... c_m and s_0, s_1, ... s_n are static constants which are can be acquired through the withOffset(VarHandle, long) and the withStride(VarHandle, long) combinators, respectively.

Alignment and access modes

A memory access var handle is associated with an access size S and an alignment constraint B (both expressed in bytes). We say that a memory access operation is fully aligned if it occurs at a memory address A which is compatible with both alignment constraints S and B. If access is fully aligned then following access modes are supported and are guaranteed to support atomic access:
  • read write access modes for all T, with the exception of access modes get and set for long and double on 32-bit platforms.
  • atomic update access modes for int, long, float or double. (Future major platform releases of the JDK may support additional types for certain currently unsupported access modes.)
  • numeric atomic update access modes for int and long. (Future major platform releases of the JDK may support additional numeric types for certain currently unsupported access modes.)
  • bitwise atomic update access modes for int and long. (Future major platform releases of the JDK may support additional numeric types for certain currently unsupported access modes.)
If T is float or double then atomic update access modes compare values using their bitwise representation (see Float.floatToRawIntBits(float) and Double.doubleToRawLongBits(double), respectively).

Alternatively, a memory access operation is partially aligned if it occurs at a memory address A which is only compatible with the alignment constraint B; in such cases, access for anything other than the get and set access modes will result in an IllegalStateException. If access is partially aligned, atomic access is only guaranteed with respect to the largest power of two that divides the GCD of A and S.

Finally, in all other cases, we say that a memory access operation is misaligned; in such cases an IllegalStateException is thrown, irrespective of the access mode being used.

  • Method Details

    • varHandle

      public static VarHandle varHandle​(Class<?> carrier, ByteOrder byteOrder)
      Creates a memory access var handle with the given carrier type and byte order. The resulting memory access var handle features a single MemoryAddress access coordinate, and its variable type is set by the given carrier type. The alignment constraint for the resulting memory access var handle is the same as the in memory size of the carrier type, and the accessed offset is set at zero.
      API Note:
      the resulting var handle features certain access mode restrictions, which are common to all memory access var handles.
      Parameters:
      carrier - the carrier type. Valid carriers are byte, short, char, int, float, long, and double.
      byteOrder - the required byte order.
      Returns:
      the new memory access var handle.
      Throws:
      IllegalArgumentException - when an illegal carrier type is used
    • varHandle

      public static VarHandle varHandle​(Class<?> carrier, long alignmentBytes, ByteOrder byteOrder)
      Creates a memory access var handle with the given carrier type, alignment constraint, and byte order. The resulting memory access var handle features a single MemoryAddress access coordinate, and its variable type is set by the given carrier type. The accessed offset is zero.
      API Note:
      the resulting var handle features certain access mode restrictions, which are common to all memory access var handles.
      Parameters:
      carrier - the carrier type. Valid carriers are byte, short, char, int, float, long, and double.
      alignmentBytes - the alignment constraint (in bytes). Must be a power of two.
      byteOrder - the required byte order.
      Returns:
      the new memory access var handle.
      Throws:
      IllegalArgumentException - if an illegal carrier type is used, or if alignmentBytes is not a power of two.
    • withOffset

      public static VarHandle withOffset​(VarHandle target, long bytesOffset)
      Creates a memory access var handle with a fixed offset added to the accessed offset. That is, if the target memory access var handle accesses a memory location at offset O, the new memory access var handle will access a memory location at offset O' + O. The resulting memory access var handle will feature the same access coordinates as the ones in the target memory access var handle.
      API Note:
      the resulting var handle features certain access mode restrictions, which are common to all memory access var handles.
      Parameters:
      target - the target memory access handle to access after the offset adjustment.
      bytesOffset - the offset, in bytes. Must be positive or zero.
      Returns:
      the new memory access var handle.
      Throws:
      IllegalArgumentException - when the target var handle is not a memory access var handle, or when bytesOffset < 0, or otherwise incompatible with the alignment constraint.
    • withStride

      public static VarHandle withStride​(VarHandle target, long bytesStride)
      Creates a memory access var handle with a variable offset added to the accessed offset. That is, if the target memory access var handle accesses a memory location at offset O, the new memory access var handle will access a memory location at offset (S * X) + O, where S is a constant stride, whereas X is a dynamic value that will be provided as an additional access coordinate (of type long). The new access coordinate will be prepended to the ones available in the target memory access var handles (if any).
      API Note:
      the resulting var handle features certain access mode restrictions, which are common to all memory access var handles.
      Parameters:
      target - the target memory access handle to access after the scale adjustment.
      bytesStride - the stride, in bytes, by which to multiply the coordinate value. Must be greater than zero.
      Returns:
      the new memory access var handle.
      Throws:
      IllegalArgumentException - when the target var handle is not a memory access var handle, or if bytesStride <= 0, or otherwise incompatible with the alignment constraint.