Interface MemoryLayout

All Known Subinterfaces:
AddressLayout,GroupLayout,PaddingLayout,SequenceLayout,StructLayout,UnionLayout,ValueLayout,ValueLayout.OfBoolean,ValueLayout.OfByte,ValueLayout.OfChar,ValueLayout.OfDouble,ValueLayout.OfFloat,ValueLayout.OfInt,ValueLayout.OfLong,ValueLayout.OfShort

public sealed interfaceMemoryLayoutpermitsSequenceLayout,GroupLayout,PaddingLayout,ValueLayout
A memory layout describes the contents of a memory segment.

There are two leaves in the layout hierarchy,value layouts, which are used to represent values of given size and kind andpadding layouts which are used, as the name suggests, to represent a portion of a memory segment whose contents should be ignored, and which are primarily present for alignment reasons. Some common value layout constants, such asValueLayout.JAVA_INT andValueLayout.JAVA_FLOAT_UNALIGNED are defined in theValueLayout class. A special kind of value layout, namely anaddress layout, is used to model values that denote the address of a region of memory.

More complex layouts can be derived from simpler ones: asequence layout denotes a homogeneous repetition of zero or more occurrences of an element layout; agroup layout denotes a heterogeneous aggregation of zero or more member layouts. Group layouts come in two flavors:struct layouts, where member layouts are laid out one after the other, andunion layouts where member layouts are laid out at the same starting offset.

Layouts can be optionally associated with aname. A layout name can be referred to when constructinglayout paths.

Consider the following struct declaration in C:

typedef struct {    char kind;    int value;} TaggedValues[5];
The above declaration can be modeled using a layout object, as follows:
SequenceLayout TAGGED_VALUES = MemoryLayout.sequenceLayout(5,    MemoryLayout.structLayout(        ValueLayout.JAVA_BYTE.withName("kind"),        MemoryLayout.paddingLayout(3),        ValueLayout.JAVA_INT.withName("value")    )).withName("TaggedValues");

Characteristics of memory layouts

All layouts have asize (expressed in bytes), which is defined as follows:
  • The size of a value layout is determined by theValueLayout.carrier() associated with the value layout. That is, the constantValueLayout.JAVA_INT has carrierint, and size of 4 bytes;
  • The size of an address layout is platform-dependent. That is, the constantValueLayout.ADDRESS has a size of 8 bytes on a 64-bit platform;
  • The size of a padding layout is always provided explicitly, onconstruction;
  • The size of a sequence layout whose element layout isE and element count isL, is the size ofE, multiplied byL;
  • The size of a struct layout with member layoutsM1,M2, ...Mn whose sizes areS1,S2, ...Sn, respectively, isS1 + S2 + ... + Sn;
  • The size of a union layoutU with member layoutsM1,M2, ...Mn whose sizes areS1,S2, ...Sn, respectively, ismax(S1, S2, ... Sn).

Furthermore, all layouts have anatural alignment (expressed in bytes) which is defined as follows:

  • The natural alignment of a padding layout is 1;
  • The natural alignment of a value layout whose size isN isN;
  • The natural alignment of a sequence layout whose element layout isE is the alignment ofE;
  • The natural alignment of a group layout with member layoutsM1,M2, ...Mn whose alignments areA1,A2, ...An, respectively, ismax(A1, A2 ... An).
A layout's alignment can be overridden if needed (seewithByteAlignment(long)), which can be useful to describe layouts with weaker or stronger alignment constraints.

Layout paths

Alayout path is used to unambiguously select a layout that is nested in some other layout. Layout paths are typically expressed as a sequence of one or morepath elements. (A more formal definition of layout paths is providedbelow).

Layout paths can be used to:

  • obtainoffsets of arbitrarily nested layouts;
  • obtain avar handle that can be used to access the value corresponding to the selected layout;
  • select an arbitrarily nested layout.

For instance, given thetaggedValues sequence layout constructed above, we can obtain the offset, in bytes, of the member layout namedvalue in thefirst sequence element, as follows:

long valueOffset = TAGGED_VALUES.byteOffset(PathElement.sequenceElement(0),                                          PathElement.groupElement("value")); // yields 4
Similarly, we can select the member layout namedvalue, as follows:
MemoryLayout value = TAGGED_VALUES.select(PathElement.sequenceElement(),                                         PathElement.groupElement("value"));

Open path elements

Some layout path elements, saidopen path elements, can select multiple layouts at once. For instance, the open path elementsMemoryLayout.PathElement.sequenceElement(),MemoryLayout.PathElement.sequenceElement(long, long) select an unspecified element in a sequence layout. A var handle derived from a layout path containing one or more open path element features additional coordinates of typelong, which can be used by clients tobind the open elements in the path:
VarHandle valueHandle = TAGGED_VALUES.varHandle(PathElement.sequenceElement(),                                               PathElement.groupElement("value"));MemorySegment taggedValues = ...// reads the "value" field of the third struct in the array (taggedValues[2].value)int val = (int) valueHandle.get(taggedValues,        0L,  // base offset        2L); // sequence index

Open path elements also affect the creation ofoffset-computing method handles. Each open path element becomes an additionallong parameter in the obtained method handle. This parameter can be used to specify the index of the sequence element whose offset is to be computed:

MethodHandle offsetHandle = TAGGED_VALUES.byteOffsetHandle(PathElement.sequenceElement(),                                                          PathElement.groupElement("kind"));long offset1 = (long) offsetHandle.invokeExact(0L, 1L); // 0 + (1 * 8) = 8long offset2 = (long) offsetHandle.invokeExact(0L, 2L); // 0 + (2 * 8) = 16

Dereference path elements

A special kind of path element, calleddereference path element, allows var handles obtained from memory layouts to follow pointers. Consider the following layout:
StructLayout RECTANGLE = MemoryLayout.structLayout(        ValueLayout.ADDRESS.withTargetLayout(                MemoryLayout.sequenceLayout(4,                        MemoryLayout.structLayout(                                ValueLayout.JAVA_INT.withName("x"),                                ValueLayout.JAVA_INT.withName("y")                        ).withName("point")                 )         ).withName("points"));
This layout is a struct layout describing a rectangle. It contains a single field, namelypoints, an address layout whosetarget layout is a sequence layout of four struct layouts. Each struct layout describes a two-dimensional point, and is defined as a pair orValueLayout.JAVA_INT coordinates, with namesx andy, respectively.

With dereference path elements, we can obtain a var handle that accesses they coordinate of one of the point in the rectangle, as follows:

VarHandle rectPointYs = RECTANGLE.varHandle(        PathElement.groupElement("points"),        PathElement.dereferenceElement(),        PathElement.sequenceElement(),        PathElement.groupElement("y"));MemorySegment rect = ...// dereferences the third point struct in the "points" array, and reads its "y" coordinate (rect.points[2]->y)int rect_y_2 = (int) rectPointYs.get(rect,    0L,  // base offset    2L); // sequence index

Layout path well-formedness

A layout path is applied to a layoutC_0, also called theinitial layout. Each path element in a layout path can be thought of as a function that updates the current layoutC_i-1 to some other layoutC_i. That is, for each path elementE1, E2, ... En, in a layout pathP, we computeC_i = f_i(C_i-1), wheref_i is the selection function associated with the path element under consideration, denoted asE_i. The final layoutC_i is also called theselected layout.

A layout pathP is considered well-formed for an initial layoutC_0 if all its path elementsE1, E2, ... En are well-formed for their corresponding input layoutsC_0, C_1, ... C_n-1. A path elementE is considered well-formed for a layoutL if any of the following is true:

Any attempt to provide a layout pathP that is not well-formed for an initial layoutC_0 will result in anIllegalArgumentException.

Access mode restrictions

A var handle returned byvarHandle(PathElement...) orValueLayout.varHandle() features certain access characteristics, which are derived from the selected layoutL:
  • A carrier typeT, derived fromL.carrier()
  • An alignment constraintA, derived fromL.byteAlignment()
  • An access sizeS, derived fromL.byteSize()
Depending on the above characteristics, the returned var handle might feature certainaccess mode restrictions. We say that a var handle isaligned if its alignment constraintA is compatible with the access sizeS, that is ifA >= S. An aligned var handle is guaranteed to support the following access modes:
  • read write access modes for allT. On 32-bit platforms, access modesget andset forlong,double andMemorySegment are supported but might lead to word tearing, as described in Section17.7. ofThe Java Language Specification.
  • atomic update access modes forint,long,float,double andMemorySegment. (Future major platform releases of the JDK may support additional types for certain currently unsupported access modes.)
  • numeric atomic update access modes forint,long andMemorySegment. (Future major platform releases of the JDK may support additional numeric types for certain currently unsupported access modes.)
  • bitwise atomic update access modes forint,long andMemorySegment. (Future major platform releases of the JDK may support additional numeric types for certain currently unsupported access modes.)
IfT isfloat,double orMemorySegment then atomic update access modes compare values using their bitwise representation (seeFloat.floatToRawIntBits(float),Double.doubleToRawLongBits(double) andMemorySegment.address(), respectively).

Alternatively, a var handle isunaligned if its alignment constraintA is incompatible with the access sizeS, that is, ifA < S. An unaligned var handle only supports theget andset access modes. All other access modes will result inUnsupportedOperationException being thrown. Moreover, while supported, access modesget andset might lead to word tearing.

Working with variable-length arrays

We have seen how sequence layouts are used to describe the contents of an array whose size is knownstatically. There are cases, however, where the array size is only knowndynamically. We call such arraysvariable-length arrays. There are two common kinds of variable-length arrays:
  • atoplevel variable-length array whose size depends on the value of some unrelated variable, or parameter;
  • an variable-length arraynested in a struct, whose size depends on the value of some other field in the enclosing struct.
While variable-length arrays cannot be modeled directly using sequence layouts, clients can still enjoy structured access to elements of variable-length arrays using var handles as demonstrated in the following sections.

Toplevel variable-length arrays

Consider the following struct declaration in C:
typedef struct {    int x;    int y;} Point;
In the above code, a point is modeled as two coordinates (x andy respectively). Now consider the following snippet of C code:
int size = ...Point *points = (Point*)malloc(sizeof(Point) * size);for (int i = 0 ; i < size ; i++) {   ... points[i].x ...}
Here, we allocate an array of points (points). Crucially, the size of the array is dynamically bound to the value of thesize variable. Inside the loop, thex coordinate of all the points in the array is accessed.

To model this code in Java, let's start by defining a layout for thePoint struct, as follows:

StructLayout POINT = MemoryLayout.structLayout(            ValueLayout.JAVA_INT.withName("x"),            ValueLayout.JAVA_INT.withName("y"));
Since we know we need to create and access an array of points, it would be tempting to create a sequence layout modelling the variable-length array, and then derive the necessary access var handles from the sequence layout. But this approach is problematic, as the size of the variable-length array is not known. Instead, a var handle that provides structured access to the elements of a variable-length array can be obtained directly from the layout describing the array elements (e.g. the point layout), as demonstrated below:
VarHandle POINT_ARR_X = POINT.arrayElementVarHandle(PathElement.groupElement("x"));int size = ...MemorySegment points = ...for (int i = 0 ; i < size ; i++) {    ... POINT_ARR_X.get(points, 0L, (long)i) ...}
Here, the coordinatex of subsequent point in the array is accessed using thePOINT_ARR_X var handle, which is obtained using thearrayElementVarHandle(PathElement...) method. This var handle features twolong coordinates: the first is a base offset (set to0L), while the second is a logical index that can be used to stride over all the elements of the point array.

The base offset coordinate allows clients to express complex access operations, by injecting additional offset computation into the var handle (we will see an example of that below). In cases where the base offset is constant (as in the previous example) clients can, if desired, drop the base offset parameter and make the access expression simpler. This is achieved using theMethodHandles.insertCoordinates(VarHandle, int, Object...) var handle adapter.

Nested variable-length arrays

Consider the following struct declaration in C:
typedef struct {    int size;    Point points[];} Polygon;
In the above code, a polygon is modeled as a size (the number of edges in the polygon) and an array of points (one for each vertex in the polygon). The number of vertices depends on the number of edges in the polygon. As such, the size of thepoints array is leftunspecified in the C declaration, using aFlexible Array Member (a feature standardized in C99).

Again, clients can perform structured access to elements in the nested variable-length array using thearrayElementVarHandle(PathElement...) method, as demonstrated below:

StructLayout POLYGON = MemoryLayout.structLayout(            ValueLayout.JAVA_INT.withName("size"),            MemoryLayout.sequenceLayout(0, POINT).withName("points"));VarHandle POLYGON_SIZE = POLYGON.varHandle(0, PathElement.groupElement("size"));long POINTS_OFFSET = POLYGON.byteOffset(PathElement.groupElement("points"));
ThePOLYGON layout contains a sequence layout of sizezero. The element layout of the sequence layout is thePOINT layout, shown previously. The polygon layout is used to obtain a var handle that provides access to the polygon size, as well as an offset (POINTS_OFFSET) to the start of the variable-lengthpoints array.

Thex coordinates of all the points in a polygon can then be accessed as follows:

MemorySegment polygon = ...int size = POLYGON_SIZE.get(polygon, 0L);for (int i = 0 ; i < size ; i++) {    ... POINT_ARR_X.get(polygon, POINTS_OFFSET, (long)i) ...}
Here, we first obtain the polygon size, using thePOLYGON_SIZE var handle. Then, in a loop, we read thex coordinates of all the points in the polygon. This is done by providing a custom offset (namely,POINTS_OFFSET) to the offset coordinate of thePOINT_ARR_X var handle. As before, the loop induction variablei is passed as the index of thePOINT_ARR_X var handle, to stride over all the elements of the variable-length array.

Implementation Requirements:
Implementations of this interface are immutable, thread-safe andvalue-based.
Sealed Class Hierarchy Graph:
Sealed class hierarchy graph for MemoryLayoutSealed class hierarchy graph for MemoryLayout
Since:
22
  • Method Details

    • byteSize

      long byteSize()
      Returns the layout size, in bytes.
      Returns:
      the layout size, in bytes
    • name

      Optional<String> name()
      Returns the name (if any) associated with this layout.
      Returns:
      the name (if any) associated with this layout
      See Also:
    • withName

      MemoryLayout withName(String name)
      Returns a memory layout with the same characteristics as this layout, but with the given name.
      Parameters:
      name - the layout name
      Returns:
      a memory layout with the same characteristics as this layout, but with the given name
      See Also:
    • withoutName

      MemoryLayout withoutName()
      Returns a memory layout with the same characteristics as this layout, but with no name.
      API Note:
      This can be useful to compare two layouts that have different names, but are otherwise equal.
      Returns:
      a memory layout with the same characteristics as this layout, but with no name
      See Also:
    • byteAlignment

      long byteAlignment()
      Returns the alignment constraint associated with this layout, expressed in bytes.

      Layout alignment defines a power of twoA which is the byte-wise alignment of the layout, whereA is the number of bytes that must be aligned for any pointer that correctly points to this layout. Thus:

      • A=1 means unaligned (in the usual sense), which is common in packets.
      • A=8 means word aligned (on LP64),A=4 int aligned,A=2 short aligned, etc.
      • A=64 is the most strict alignment required by the x86/SV ABI (for AVX-512 data).
      If no explicit alignment constraint was set on this layout ( seewithByteAlignment(long)), then this method returns thenatural alignment constraint (in bytes) associated with this layout.

      Returns:
      the alignment constraint associated with this layout, expressed in bytes
    • withByteAlignment

      MemoryLayout withByteAlignment(long byteAlignment)
      Returns a memory layout with the same characteristics as this layout, but with the given alignment constraint (in bytes).
      Parameters:
      byteAlignment - the layout alignment constraint, expressed in bytes
      Returns:
      a memory layout with the same characteristics as this layout, but with the given alignment constraint (in bytes)
      Throws:
      IllegalArgumentException - ifbyteAlignment is not a power of two
    • scale

      long scale(long offset, long index)
      Returnsoffset + (byteSize() * index).
      Parameters:
      offset - the base offset
      index - the index to be scaled by the byte size of this layout
      Returns:
      offset + (byteSize() * index)
      Throws:
      IllegalArgumentException - ifoffset orindex is negative
      ArithmeticException - if either the addition or multiplication overflows
    • scaleHandle

      MethodHandle scaleHandle()
      Returns a method handle that can be used to invokescale(long, long) on this layout.
      Returns:
      a method handle that can be used to invokescale(long, long) on this layout
    • byteOffset

      long byteOffset(MemoryLayout.PathElement... elements)
      Computes the offset, in bytes, of the layout selected by the given layout path, where the initial layout in the path is this layout.
      Parameters:
      elements - the layout path elements
      Returns:
      The offset, in bytes, of the layout selected by the layout path inelements
      Throws:
      IllegalArgumentException - if the layout path is notwell-formed for this layout
      IllegalArgumentException - if the layout path contains one or moreopen path elements
      IllegalArgumentException - if the layout path contains one or moredereference path elements
    • byteOffsetHandle

      MethodHandle byteOffsetHandle(MemoryLayout.PathElement... elements)
      Creates a method handle that computes the offset, in bytes, of the layout selected by the given layout path, where the initial layout in the path is this layout.

      The returned method handle has the following characteristics:

      • its return type islong;
      • it has one leadinglong parameter representing the base offset;
      • it has as zero or more trailing parameters of typelong, one for eachopen path element in the provided layout path. The order of these parameters corresponds to the order in which the open path elements occur in the provided layout path.

      The final offset returned by the method handle is computed as follows:

       offset = b + c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
      whereb represents the base offset provided as adynamiclong argument,x_1,x_2, ...x_n represent indices into sequences provided asdynamiclong arguments, whereass_1,s_2, ...s_n arestatic stride constants derived from the size of the element layout of a sequence, andc_1,c_2, ...c_m are otherstatic offset constants (such as field offsets) which are derived from the layout path.

      For any given dynamic argumentx_i, it must be that0 <= x_i < size_i, wheresize_i is the size of the open path element associated withx_i. Otherwise, the returned method handle throwsIndexOutOfBoundsException. Moreover, the value ofb must be such that the computation foroffset does not overflow, or the returned method handle throwsArithmeticException.

      API Note:
      The returned method handle can be used to compute a layout offset, similarly tobyteOffset(PathElement...), but more flexibly, as some indices can be specified when invoking the method handle.
      Parameters:
      elements - the layout path elements
      Returns:
      a method handle that computes the offset, in bytes, of the layout selected by the given layout path
      Throws:
      IllegalArgumentException - if the layout path is notwell-formed for this layout
      IllegalArgumentException - if the layout path contains one or moredereference path elements
    • varHandle

      VarHandle varHandle(MemoryLayout.PathElement... elements)
      Creates a var handle that accesses a memory segment at the offset selected by the given layout path, where the initial layout in the path is this layout.

      The returned var handle has the following characteristics:

      • its type is derived from thecarrier of the selected value layout;
      • it has a leading parameter of typeMemorySegment representing the accessed segment
      • a followinglong parameter, corresponding to the base offset, denoted asB;
      • it has zero or more trailing access coordinates of typelong, one for eachopen path element in the provided layout path, denoted asI1, I2, ... In, respectively. The order of these access coordinates corresponds to the order in which the open path elements occur in the provided layout path.

      If the provided layout pathP contains no dereference elements, then the offsetO of the access operation is computed as follows:

      O = this.byteOffsetHandle(P).invokeExact(B, I1, I2, ... In);

      Accessing a memory segment using the var handle returned by this method is subject to the following checks:

      • The physical address of the accessed memory segment must bealigned according to thealignment constraint of the root layout (this layout), or anIllegalArgumentException is thrown. Note that the alignment constraint of the root layout can be more strict (but not less) than the alignment constraint of the selected value layout.
      • The access operation must fall inside the spatial bounds of the accessed memory segment, or anIndexOutOfBoundsException is thrown. This is the case whenB + A <= S, whereB is the base offset (defined above),A is the size of this layout andS is the size of the accessed memory segment. Note that the size of this layout might bebigger than the size of the accessed layout (e.g. when accessing a struct member).
      • If the provided layout path has an open path element whose size isS, its corresponding trailinglong coordinate valueI must be0 <= I < S, or anIndexOutOfBoundsException is thrown.
      • The accessed memory segment must beaccessible from the thread performing the access operation, or aWrongThreadException is thrown.
      • For write operations, the accessed memory segment must not beread only, or anIllegalArgumentException is thrown.
      • Thescope associated with the accessed segment must bealive, or anIllegalStateException is thrown.

      If the selected layout is anaddress layout, callingVarHandle.get(Object...) on the returned var handle will return a new memory segment. The segment is associated with the global scope. Moreover, the size of the segment depends on whether the address layout has atarget layout. More specifically:

      • If the address layout has a target layoutT, then the size of the returned segment isT.byteSize();
      • Otherwise, the address layout has no target layout and the size of the returned segment iszero.
      Moreover, if the selected layout is anaddress layout, callingVarHandle.set(Object...) can throwIllegalArgumentException if the memory segment representing the address to be written is not anative memory segment.

      If the provided layout path has sizem and contains a dereference path element in positionk (wherek <= m) then two layout pathsP andQ are derived, where P contains all the path elements from 0 tok - 1 andQ contains all the path elements fromk + 1 tom (Q could be an empty layout path ifk == m). Then, the returned var handle is computed as follows:

      VarHandle baseHandle = this.varHandle(P);MemoryLayout target = ((AddressLayout)this.select(P)).targetLayout().get();VarHandle targetHandle = target.varHandle(Q);targetHandle = MethodHandles.insertCoordinates(targetHandle, 1, 0L); // always access nested targets at offset 0targetHandle = MethodHandles.collectCoordinates(targetHandle, 0,        baseHandle.toMethodHandle(VarHandle.AccessMode.GET));
      (The above can be trivially generalized to cases where the provided layout path contains more than one dereference path elements).

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

          GroupLayout grp = java.lang.foreign.MemoryLayout.structLayout(            MemoryLayout.paddingLayout(4),            ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withName("value")    );
      To access the member layout namedvalue, we can construct a var handle as follows:
          VarHandle handle = grp.varHandle(PathElement.groupElement("value")); //(MemorySegment, long) -> int

      API Note:
      The resulting var handle features certainaccess mode restrictions, which are common to all var handles derived from memory layouts.
      Parameters:
      elements - the layout path elements
      Returns:
      a var handle that accesses a memory segment at the offset selected by the given layout path
      Throws:
      IllegalArgumentException - if the layout path is notwell-formed for this layout
      IllegalArgumentException - if the layout selected by the provided path is not avalue layout
    • arrayElementVarHandle

      VarHandle arrayElementVarHandle(MemoryLayout.PathElement... elements)
      Creates a var handle that accesses adjacent elements in a memory segment at offsets selected by the given layout path, where the accessed elements have this layout, and where the initial layout in the path is this layout.

      The returned var handle has the following characteristics:

      • its type is derived from thecarrier of the selected value layout;
      • it has a leading parameter of typeMemorySegment representing the accessed segment
      • a followinglong parameter, corresponding to the base offset, denoted asB;
      • a followinglong parameter, corresponding to the array index, denoted asI0. The array index is used to scale the accessed offset by this layout size;
      • it has zero or more trailing access coordinates of typelong, one for eachopen path element in the provided layout path, denoted asI1, I2, ... In, respectively. The order of these access coordinates corresponds to the order in which the open path elements occur in the provided layout path.

      If the provided layout pathP contains no dereference elements, then the offsetO of the access operation is computed as follows:

      O = this.byteOffsetHandle(P).invokeExact(this.scale(B, I0), I1, I2, ... In);

      More formally, the method handle returned by this method is obtained fromvarHandle(PathElement...), as follows:

      MethodHandles.collectCoordinates(varHandle(elements), 1, scaleHandle())

      Accessing a memory segment using the var handle returned by this method is subject to the following checks:

      • The physical address of the accessed memory segment must bealigned according to thealignment constraint of the root layout (this layout), or anIllegalArgumentException is thrown. Note that the alignment constraint of the root layout can be more strict (but not less) than the alignment constraint of the selected value layout.
      • The access operation must fall inside the spatial bounds of the accessed memory segment, or anIndexOutOfBoundsException is thrown. This is the case whenB + A <= S, whereB is the base offset (defined above),A is the size of this layout andS is the size of the accessed memory segment. Note that the size of this layout might bebigger than the size of the accessed layout (e.g. when accessing a struct member).
      • If the provided layout path has an open path element whose size isS, its corresponding trailinglong coordinate valueI must be0 <= I < S, or anIndexOutOfBoundsException is thrown.
      • The accessed memory segment must beaccessible from the thread performing the access operation, or aWrongThreadException is thrown.
      • For write operations, the accessed memory segment must not beread only, or anIllegalArgumentException is thrown.
      • Thescope associated with the accessed segment must bealive, or anIllegalStateException is thrown.

      API Note:
      As the leading index coordinateI0 is not bound by any sequence layout, it can assumeany non-negative value - provided that the resulting offset computation does not overflow, or that the computed offset does not fall outside the spatial bound of the accessed memory segment. As such, the var handles returned from this method can be especially useful when accessingvariable-length arrays.
      Parameters:
      elements - the layout path elements
      Returns:
      a var handle that accesses adjacent elements in a memory segment at offsets selected by the given layout path
      Throws:
      IllegalArgumentException - if the layout path is notwell-formed for this layout
      IllegalArgumentException - if the layout selected by the provided path is not avalue layout
    • sliceHandle

      MethodHandle sliceHandle(MemoryLayout.PathElement... elements)
      Creates a method handle which, given a memory segment, returns aslice corresponding to the layout selected by the given layout path, where the initial layout in the path is this layout.

      The returned method handle has the following characteristics:

      • its return type isMemorySegment;
      • it has a leading parameter of typeMemorySegment corresponding to the memory segment to be sliced
      • a followinglong parameter, corresponding to the base offset
      • it has as zero or more trailing parameters of typelong, one for eachopen path element in the provided layout path. The order of these parameters corresponds to the order in which the open path elements occur in the provided layout path.

      The offsetO of the returned segment is computed as if by a call to abyte offset handle constructed using the given path elements.

      Computing a slice of a memory segment using the method handle returned by this method is subject to the following checks:

      • The physical address of the accessed memory segment must bealigned according to thealignment constraint of the root layout (this layout), or anIllegalArgumentException will be issued. Note that the alignment constraint of the root layout can be more strict (but not less) than the alignment constraint of the selected layout.
      • The slicing operation must fall inside the spatial bounds of the accessed memory segment, or anIndexOutOfBoundsException is thrown. This is the case whenB + A <= S, whereB is the base offset (defined above),A is the size of this layout andS is the size of the accessed memory segment. Note that the size of this layout might bebigger than the size of the accessed layout (e.g. when accessing a struct member).
      • If the provided layout path has an open path element whose size isS, its corresponding trailinglong coordinate valueI must be0 <= I < S, or anIndexOutOfBoundsException is thrown.

      API Note:
      The returned method handle can be used to obtain a memory segment slice, similarly toMemorySegment.asSlice(long, long), but more flexibly, as some indices can be specified when invoking the method handle.
      Parameters:
      elements - the layout path elements
      Returns:
      a method handle that is used to slice a memory segment at the offset selected by the given layout path
      Throws:
      IllegalArgumentException - if the layout path is notwell-formed for this layout
      IllegalArgumentException - if the layout path contains one or moredereference path elements
    • select

      Returns the layout selected from the provided path, where the initial layout in the path is this layout.
      Parameters:
      elements - the layout path elements
      Returns:
      the layout selected by the layout path inelements
      Throws:
      IllegalArgumentException - if the layout path is notwell-formed for this layout
      IllegalArgumentException - if the layout path contains one or moredereference path elements
      IllegalArgumentException - if the layout path contains one or more path elements that select one or more sequence element indices, such asMemoryLayout.PathElement.sequenceElement(long) andMemoryLayout.PathElement.sequenceElement(long, long))
    • equals

      boolean equals(Object other)
      Compares the specified object with this layout for equality. Returnstrue if and only if the specified object is also a layout, and it is equal to this layout. Two layouts are considered equal if they are of the same kind, have the same size, name and alignment constraint. Furthermore, depending on the layout kind, additional conditions must be satisfied:
      Overrides:
      equals in class Object
      Parameters:
      other - the object to be compared for equality with this layout
      Returns:
      true if the specified object is equal to this layout
      See Also:
    • hashCode

      int hashCode()
      Returns the hash code value for this layout.
      Overrides:
      hashCode in class Object
      Returns:
      the hash code value for this layout
      See Also:
    • toString

      String toString()
      Returns the string representation of this layout.
      Overrides:
      toString in class Object
      Returns:
      the string representation of this layout
    • paddingLayout

      static PaddingLayout paddingLayout(long byteSize)
      Creates a padding layout with the given byte size. The alignment constraint of the returned layout is 1. As such, regardless of its size, in the absence of anexplicit alignment constraint, a padding layout does not affect the natural alignment of the group or sequence layout it is nested into.
      Parameters:
      byteSize - the padding size (expressed in bytes)
      Returns:
      the new selector layout
      Throws:
      IllegalArgumentException - ifbyteSize <= 0
    • sequenceLayout

      static SequenceLayout sequenceLayout(long elementCount,MemoryLayout elementLayout)
      Creates a sequence layout with the given element layout and element count.
      Parameters:
      elementCount - the sequence element count
      elementLayout - the sequence element layout
      Returns:
      the new sequence layout with the given element layout and size
      Throws:
      IllegalArgumentException - ifelementCount is negative
      IllegalArgumentException - ifelementLayout.byteSize() * elementCount overflows
      IllegalArgumentException - ifelementLayout.byteSize() % elementLayout.byteAlignment() != 0
    • structLayout

      static StructLayout structLayout(MemoryLayout... elements)
      Creates a struct layout with the given member layouts.
      API Note:
      This factory does not automatically align element layouts, by inserting additionalpadding layout elements. As such, the following struct layout creation will fail with an exception:
      structLayout(JAVA_SHORT, JAVA_INT);
      To avoid the exception, clients can either insert additional padding layout elements:
      structLayout(JAVA_SHORT, MemoryLayout.paddingLayout(2), JAVA_INT);
      Or, alternatively, they can use a member layout that features a smaller alignment constraint. This will result in apacked struct layout:
      structLayout(JAVA_SHORT, JAVA_INT.withByteAlignment(2));
      Parameters:
      elements - The member layouts of the struct layout
      Returns:
      a struct layout with the given member layouts
      Throws:
      IllegalArgumentException - if the sum of thebyte sizes of the member layouts overflows
      IllegalArgumentException - if a member layout inelements occurs at an offset (relative to the start of the struct layout) which is not compatible with its alignment constraint
    • unionLayout

      static UnionLayout unionLayout(MemoryLayout... elements)
      Creates a union layout with the given member layouts.
      Parameters:
      elements - The member layouts of the union layout
      Returns:
      a union layout with the given member layouts