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
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, torepresent a portion of a memory segment whose contents should be ignored, and whichare primarily present for alignment reasons. Some common value layout constants, suchasValueLayout.JAVA_INT andValueLayout.JAVA_FLOAT_UNALIGNED aredefined in theValueLayout class. A special kind of value layout, namely anaddress layout, is used to model values that denote theaddress of a region of memory.
More complex layouts can be derived from simpler ones: asequence layout denotes a homogeneous repetition of zeroor more occurrences of an element layout; agroup layoutdenotes a heterogeneous aggregation of zero or more member layouts. Group layoutscome in two flavors:struct layouts, where member layoutsare laid out one after the other, andunion layouts wheremember layouts are laid out at the same starting offset.
Layouts can be optionally associated with aname. A layout name can bereferred to when constructinglayout paths.
Consider the following struct declaration in C:
typedef struct { char kind; int value;} TaggedValues[5];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 constant
ValueLayout.JAVA_INThas carrierint, and size of 4 bytes; - The size of an address layout is platform-dependent. That is, the constant
ValueLayout.ADDRESShas 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) whichis 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).
withByteAlignment(long)), which can be useful to describelayouts with weaker or stronger alignment constraints.Layout paths
Alayout path is used to unambiguously select a layout that is nested in someother layout. Layout paths are typically expressed as a sequence of one or morepath elements. (A more formal definition of layout paths isprovidedbelow).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 canobtain 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 4value, as follows:MemoryLayout value = TAGGED_VALUES.select(PathElement.sequenceElement(), PathElement.groupElement("value"));Open path elements
Some layout path elements, saidopen path elements, can select multiplelayouts 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 alayout path containing one or more open path element features additional coordinatesof typelong, which can be used by clients tobind the open elementsin 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 indexOpen path elements also affect the creation ofoffset-computing method handles. Eachopen path element becomes an additionallong parameter in the obtained methodhandle. This parameter can be used to specify the index of the sequence element whoseoffset 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) = 16Dereference path elements
A special kind of path element, calleddereference path element, allows varhandles 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"));points, an address layout whosetarget layout is a sequence layout of fourstruct layouts. Each struct layout describes a two-dimensional point, and is definedas 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 thepoint 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 indexLayout 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 afunction 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 selectionfunction 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_0if all its path elementsE1, E2, ... En are well-formed for theircorresponding input layoutsC_0, C_1, ... C_n-1. A path elementE isconsidered well-formed for a layoutL if any of the following is true:
Lis a sequence layout andEis a sequence path element(one ofMemoryLayout.PathElement.sequenceElement(long),MemoryLayout.PathElement.sequenceElement(long, long)orMemoryLayout.PathElement.sequenceElement()). Moreover, ifEcontains one ormore sequence indices, such indices have to be compatible with the sequence layout'selement count;Lis a group layout andEis a group path element (one ofMemoryLayout.PathElement.groupElement(String)orMemoryLayout.PathElement.groupElement(long)).Moreover, the group path element must refer to a valid member layout inL, either by name, or index;Lis an address layout andEis adereference path element.Moreover,Lmust define sometarget layout.
P that is not well-formed for an initiallayoutC_0 will result in anIllegalArgumentException.Access mode restrictions
A var handle returned byvarHandle(PathElement...) orValueLayout.varHandle() features certain access characteristics, which arederived from the selected layoutL:- A carrier type
T, derived fromL.carrier() - An alignment constraint
A, derived fromL.byteAlignment() - An access size
S, derived fromL.byteSize()
A is compatible with the access sizeS, that isifA >= S. An aligned var handle is guaranteed to support the followingaccess modes:- read write access modes for all
T. Access modesgetandsetforlong,doubleandMemorySegmentare supported but have no atomicity guarantee, as described in Section17.7 ofThe Java Language Specification. - atomic update access modes for
int,long,float,doubleandMemorySegment. (Future major platform releases of the JDK may support additional types for certain currently unsupported access modes.) - numeric atomic update access modes for
int,longandMemorySegment. (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,longandMemorySegment. (Future major platform releases of the JDK may support additional numeric types for certain currently unsupported access modes.)
T isfloat,double orMemorySegment then atomicupdate 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 constraintAis incompatible with the access sizeS, that is, ifA < S. Anunaligned var handle only supports theget andset access modes. Allother access modes will result inUnsupportedOperationException being thrown.Moreover, while supported, access modesget andset might lead toword tearing.
Working with variable-length arrays
We have seen how sequence layouts are used to describe the contents of an array whosesize is knownstatically. There are cases, however, where the array size isonly 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.
Toplevel variable-length arrays
Consider the following struct declaration in C:typedef struct { int x; int y;} Point;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 ...}points). Crucially, the size ofthe array is dynamically bound to the value of thesize variable. Insidethe 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 thePointstruct, as follows:
StructLayout POINT = MemoryLayout.structLayout( ValueLayout.JAVA_INT.withName("x"), ValueLayout.JAVA_INT.withName("y"));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) ...}x 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 thesecond is a logical index that can be used to stride over all the elements of thepoint array.The base offset coordinate allows clients to express complex access operations, byinjecting additional offset computation into the var handle (we will see an exampleof that below). In cases where the base offset is constant (as in the previousexample) clients can, if desired, drop the base offset parameter and make the accessexpression 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;pointsarray 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-lengtharray using thearrayElementVarHandle(PathElement...) method, as demonstratedbelow:
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"));POLYGON layout contains a sequence layout of sizezero. Theelement 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 polygonsize, 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 asfollows:
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) ...}POLYGON_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 theoffset coordinate of thePOINT_ARR_X var handle. As before, the loopinduction variablei is passed as the index of thePOINT_ARR_Xvar 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:
- Since:
- 22
Nested Class Summary
Nested ClassesMethod Summary
Modifier and TypeMethodDescriptionarrayElementVarHandle(MemoryLayout.PathElement... elements) Creates a var handle that accesses adjacent elements in a memory segment atoffsets selected by the given layout path, where the accessed elements have thislayout, and where the initial layout in the path is this layout.longReturns the alignment constraint associated with this layout, expressed in bytes.longbyteOffset(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.byteOffsetHandle(MemoryLayout.PathElement... elements) Creates a method handle that computes the offset, in bytes, of the layout selectedby the given layout path, where the initial layout in the path is this layout.longbyteSize()Returns the layout size, in bytes.booleanCompares the specified object with this layout for equality.inthashCode()Returns the hash code value for this layout.name()Returns the name (if any) associated with this layout.staticPaddingLayoutpaddingLayout(long byteSize) Creates a padding layout with the given byte size.longscale(long offset, long index) Returnsoffset + (byteSize() * index).Returns a method handle that can be used to invokescale(long, long)on this layout.select(MemoryLayout.PathElement... elements) Returns the layout selected from the provided path, where the initial layout inthe path is this layout.staticSequenceLayoutsequenceLayout(long elementCount,MemoryLayout elementLayout) Creates a sequence layout with the given element layout and element count.sliceHandle(MemoryLayout.PathElement... elements) Creates a method handle which, given a memory segment, returns aslice corresponding tothe layout selected by the given layout path, where the initial layout inthe path is this layout.staticStructLayoutstructLayout(MemoryLayout... elements) Creates a struct layout with the given member layouts.toString()Returns the string representation of this layout.staticUnionLayoutunionLayout(MemoryLayout... elements) Creates a union layout with the given member layouts.varHandle(MemoryLayout.PathElement... elements) Creates a var handle that accesses a memory segment at the offset selected by thegiven layout path, where the initial layout in the path is this layout.withByteAlignment(long byteAlignment) Returns a memory layout with the same characteristics as this layout, but with the given alignment constraint (in bytes).Returns a memory layout with the same characteristics as this layout, but with the given name.Returns a memory layout with the same characteristics as this layout, but with no name.
Method Details
byteSize
long byteSize()Returns the layout size, in bytes.- Returns:
- the layout size, in bytes
name
Returns the name (if any) associated with this layout.- Returns:
- the name (if any) associated with this layout
- See Also:
withName
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 two
Awhich is the byte-wise alignmentof the layout, whereAis the number of bytes that must be aligned for anypointer that correctly points to this layout. Thus:A=1means unaligned (in the usual sense), which is common in packets.A=8means word aligned (on LP64),A=4int aligned,A=2short aligned, etc.A=64is the most strict alignment required by the x86/SV ABI(for AVX-512 data).
withByteAlignment(long)), then this method returns thenatural alignment constraint (in bytes) associatedwith this layout.- Returns:
- the alignment constraint associated with this layout, expressed in bytes
withByteAlignment
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- ifbyteAlignmentis not a power of two
scale
long scale(long offset, long index) Returnsoffset + (byteSize() * index).- Parameters:
offset- the base offsetindex- the index to be scaled by the byte size of this layout- Returns:
offset + (byteSize() * index)- Throws:
IllegalArgumentException- ifoffsetorindexis negativeArithmeticException- 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 invoke
scale(long, long)on this layout
byteOffset
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 in
elements - Throws:
IllegalArgumentException- if the layout path is notwell-formed for this layoutIllegalArgumentException- if the layout path contains one or moreopen path elementsIllegalArgumentException- if the layout path contains one or moredereference path elements
byteOffsetHandle
Creates a method handle that computes the offset, in bytes, of the layout selectedby 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 is
long; - it has one leading
longparameter representing the base offset; - it has as zero or more trailing parameters of type
long, 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:
whereoffset = b + c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)brepresents the base offset provided as adynamiclongargument,x_1,x_2, ...x_nrepresent indicesinto sequences provided asdynamiclongarguments, whereass_1,s_2, ...s_narestatic stride constantsderived from the size of the element layout of a sequence, andc_1,c_2, ...c_mare otherstatic offsetconstants (such as field offsets) which are derived from the layout path.For any given dynamic argument
x_i, it must be that0 <= x_i < size_i,wheresize_iis the size of the open path element associated withx_i.Otherwise, the returned method handle throwsIndexOutOfBoundsException. Moreover,the value ofbmust be such that the computation foroffsetdoes not overflow,or the returned method handle throwsArithmeticException.- API Note:
- The returned method handle can be used to compute a layout offset, similarly to
byteOffset(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 layoutIllegalArgumentException- if the layout path contains one or moredereference path elements
- its return type is
varHandle
Creates a var handle that accesses a memory segment at the offset selected by thegiven 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 type
MemorySegmentrepresenting the accessed segment - a following
longparameter, corresponding to the base offset, denoted asB; - it has zero or more trailing access coordinates of type
long, 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 path
Pcontains no dereference elements, then theoffsetOof 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 subjectto the following checks:
- The physical address of the accessed memory segment must bealigned according to thealignment constraint of the root layout (this layout), or an
IllegalArgumentExceptionis 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 an
IndexOutOfBoundsExceptionis thrown. This is the case whenB + A <= S, whereBis the base offset (defined above),Ais the size of this layout andSis 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 is
S, its corresponding trailinglongcoordinate valueImust be0 <= I < S, or anIndexOutOfBoundsExceptionis thrown. - The accessed memory segment must be
accessiblefrom the thread performing the access operation, or aWrongThreadExceptionis thrown. - For write operations, the accessed memory segment must not be
read only, or anIllegalArgumentExceptionis thrown. - Thescope associated with the accessed segment must bealive, or an
IllegalStateExceptionis thrown.
If the selected layout is anaddress layout, calling
VarHandle.get(Object...)on the returned var handle will return a newmemory segment. The segment is associated with the global scope. Moreover, thesize of the segment depends on whether the address layout has atarget layout. More specifically:- If the address layout has a target layout
T, 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.
VarHandle.set(Object...)can throwIllegalArgumentExceptionif the memory segment representing the address to be written is not anative memory segment.If the provided layout path has size
mand contains a dereference pathelement in positionk(wherek <= m) then two layout pathsPandQare derived, where P contains all the path elements from0 tok - 1andQcontains all the path elements fromk + 1tom(Qcould be an empty layout path ifk == m).Then, the returned var handle is computed as follows:(The above can be trivially generalized to cases where the provided layout pathcontains more than one dereference path elements).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));As an example, consider the memory layout expressed by a
GroupLayoutinstance constructed as follows:To access the member layout namedGroupLayout grp = java.lang.foreign.MemoryLayout.structLayout( MemoryLayout.paddingLayout(4), ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withName("value") );value, we can construct a var handle asfollows:VarHandle handle = grp.varHandle(PathElement.groupElement("value")); //(MemorySegment, long) -> int- API Note:
- The resulting var handle features certainaccess mode restrictions, whichare 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 layoutIllegalArgumentException- if the layout selected by the provided path is not avalue layout
arrayElementVarHandle
Creates a var handle that accesses adjacent elements in a memory segment atoffsets selected by the given layout path, where the accessed elements have thislayout, 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 type
MemorySegmentrepresenting the accessed segment - a following
longparameter, corresponding to the base offset, denoted asB; - a following
longparameter, 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 type
long, 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 path
Pcontains no dereference elements, then theoffsetOof 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 from
varHandle(PathElement...),as follows:MethodHandles.collectCoordinates(varHandle(elements), 1, scaleHandle())Accessing a memory segment using the var handle returned by this method is subjectto the following checks:
- The physical address of the accessed memory segment must bealigned according to thealignment constraint of the root layout (this layout), or an
IllegalArgumentExceptionis 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 an
IndexOutOfBoundsExceptionis thrown. This is the case whenB + A <= S, whereBis the base offset (defined above),Ais the size of this layout andSis 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 is
S, its corresponding trailinglongcoordinate valueImust be0 <= I < S, or anIndexOutOfBoundsExceptionis thrown. - The accessed memory segment must be
accessiblefrom the thread performing the access operation, or aWrongThreadExceptionis thrown. - For write operations, the accessed memory segment must not be
read only, or anIllegalArgumentExceptionis thrown. - Thescope associated with the accessed segment must bealive, or an
IllegalStateExceptionis thrown.
- API Note:
- As the leading index coordinate
I0is not bound by any sequence layout, itcan assumeany non-negative value - provided that the resulting offsetcomputation does not overflow, or that the computed offset does not fall outsidethe spatial bound of the accessed memory segment. As such, the var handlesreturned 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 layoutIllegalArgumentException- if the layout selected by the provided path is not avalue layout
sliceHandle
Creates a method handle which, given a memory segment, returns aslice corresponding tothe layout selected by the given layout path, where the initial layout inthe path is this layout.The returned method handle has the following characteristics:
- its return type is
MemorySegment; - it has a leading parameter of type
MemorySegmentcorresponding to the memory segment to be sliced - a following
longparameter, corresponding to the base offset - it has as zero or more trailing parameters of type
long, 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 offset
Oof the returned segment is computed as if by a call to abyte offset handle constructedusing the given path elements.Computing a slice of a memory segment using the method handle returned by thismethod 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 an
IllegalArgumentExceptionwill 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 an
IndexOutOfBoundsExceptionis thrown. This is the case whenB + A <= S, whereBis the base offset (defined above),Ais the size of this layout andSis 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 is
S, its corresponding trailinglongcoordinate valueImust be0 <= I < S, or anIndexOutOfBoundsExceptionis thrown.
- API Note:
- The returned method handle can be used to obtain a memory segment slice, similarly to
MemorySegment.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 layoutIllegalArgumentException- if the layout path contains one or moredereference path elements
- its return type is
select
Returns the layout selected from the provided path, where the initial layout inthe path is this layout.- Parameters:
elements- the layout path elements- Returns:
- the layout selected by the layout path in
elements - Throws:
IllegalArgumentException- if the layout path is notwell-formed for this layoutIllegalArgumentException- if the layout path contains one or moredereference path elementsIllegalArgumentException- 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
Compares the specified object with this layout for equality. Returnstrueif and only if the specified object is also a layout, and it is equal to thislayout. Two layouts are considered equal if they are of the same kind, have thesame size, name and alignment constraint. Furthermore, depending on thelayout kind, additional conditions must be satisfied:- two value layouts are considered equal if they have the sameorder, andcarrier. Additionally, two address layouts are considered equal if they also have the sametarget layout;
- two sequence layouts are considered equal if they have the same element count (see
SequenceLayout.elementCount()), and if their element layouts (seeSequenceLayout.elementLayout()) are also equal; - two group layouts are considered equal if they are of the same type (see
StructLayout,UnionLayout) and if their member layouts (seeGroupLayout.memberLayouts()) are also equal.
hashCode
toString
paddingLayout
Creates a padding layout with the given byte size. The alignment constraint of thereturned layout is 1. As such, regardless of its size, in the absence of anexplicit alignment constraint, a paddinglayout does not affect the natural alignment of the group or sequence layout it isnested into.- Parameters:
byteSize- the padding size (expressed in bytes)- Returns:
- the new selector layout
- Throws:
IllegalArgumentException- ifbyteSize <= 0
sequenceLayout
Creates a sequence layout with the given element layout and element count.- Parameters:
elementCount- the sequence element countelementLayout- the sequence element layout- Returns:
- the new sequence layout with the given element layout and size
- Throws:
IllegalArgumentException- ifelementCountis negativeIllegalArgumentException- ifelementLayout.byteSize() * elementCountoverflowsIllegalArgumentException- ifelementLayout.byteSize() % elementLayout.byteAlignment() != 0
structLayout
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:To avoid the exception, clients can either insert additional padding layoutelements:
structLayout(JAVA_SHORT, JAVA_INT);Or, alternatively, they can use a member layout that features a smaller alignmentconstraint. This will result in apacked struct layout:structLayout(JAVA_SHORT, MemoryLayout.paddingLayout(2), JAVA_INT);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 overflowsIllegalArgumentException- if a member layout inelementsoccurs at an offset (relative to the start of the struct layout) which is not compatible with its alignment constraint
unionLayout
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