AddressLayoutPREVIEW
, GroupLayoutPREVIEW
, PaddingLayoutPREVIEW
, SequenceLayoutPREVIEW
, StructLayoutPREVIEW
, UnionLayoutPREVIEW
, ValueLayoutPREVIEW
, ValueLayout.OfBooleanPREVIEW
, ValueLayout.OfBytePREVIEW
, ValueLayout.OfCharPREVIEW
, ValueLayout.OfDoublePREVIEW
, ValueLayout.OfFloatPREVIEW
, ValueLayout.OfIntPREVIEW
, ValueLayout.OfLongPREVIEW
, ValueLayout.OfShortPREVIEW
public sealed interface MemoryLayout permits SequenceLayoutPREVIEW, GroupLayoutPREVIEW, PaddingLayoutPREVIEW, ValueLayoutPREVIEW
MemoryLayout
is a preview API of the Java platform. There are two leaves in the layout hierarchy, value layoutsPREVIEW, which are used to represent values of given size and kind (see and padding layoutsPREVIEW 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 as ValueLayout.JAVA_INT
PREVIEW and ValueLayout.JAVA_FLOAT_UNALIGNED
PREVIEW are defined in the ValueLayout
PREVIEW class. A special kind of value layout, namely an address layoutPREVIEW, is used to model values that denote the address of a region of memory.
More complex layouts can be derived from simpler ones: a sequence layoutPREVIEW denotes a homogeneous repetition of zero or more occurrences of an element layout; a group layoutPREVIEW denotes a heterogeneous aggregation of zero or more member layouts. Group layouts come in two flavors: struct layoutsPREVIEW, where member layouts are laid out one after the other, and union layoutsPREVIEW where member layouts are laid out at the same starting offset.
Layouts can be optionally associated with a name. A layout name can be referred to when constructing layout paths.
Consider the following struct declaration in C:
typedef struct {
char kind;
int value;
} TaggedValues[5];
SequenceLayout taggedValues = MemoryLayout.sequenceLayout(5,
MemoryLayout.structLayout(
ValueLayout.JAVA_BYTE.withName("kind"),
MemoryLayout.paddingLayout(3),
ValueLayout.JAVA_INT.withName("value")
)
).withName("TaggedValues");
ValueLayout.JAVA_INT
PREVIEW has carrier int
, and size of 4 bytes;ValueLayout.ADDRESS
PREVIEW has size of 8 bytes on a 64-bit platform;Furthermore, all layouts have a natural alignment (expressed in bytes) which is defined as follows:
withByteAlignment(long)
), which can be useful to describe layouts with weaker or stronger alignment constraints. Layout paths can be used to:
For instance, given the taggedValues
sequence layout constructed above, we can obtain the offset, in bytes, of the member layout named value
in the first sequence element, as follows:
long valueOffset = taggedValues.byteOffset(PathElement.sequenceElement(0),
PathElement.groupElement("value")); // yields 4
value
, as follows: MemoryLayout value = taggedValues.select(PathElement.sequenceElement(),
PathElement.groupElement("value"));
MemoryLayout.PathElement.sequenceElement()
PREVIEW, MemoryLayout.PathElement.sequenceElement(long, long)
PREVIEW 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 type long
, which can be used by clients to bind the open elements in the path: VarHandle valueHandle = taggedValues.varHandle(PathElement.sequenceElement(),
PathElement.groupElement("value"));
MemorySegment valuesSegment = ...
int val = (int) valueHandle.get(valuesSegment, 2); // reads the "value" field of the third struct in the array
Open path elements also affects the creation of offset-computing method handles. Each open path element becomes an additional long
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 = taggedValues.byteOffsetHandle(PathElement.sequenceElement(),
PathElement.groupElement("kind"));
long offset1 = (long) offsetHandle.invokeExact(1L); // 8
long offset2 = (long) offsetHandle.invokeExact(2L); // 16
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 whose target layoutPREVIEW is a sequence layout of four struct layouts. Each struct layout describes a two-dimensional point, and is defined as a pair or ValueLayout.JAVA_INT
PREVIEW coordinates, with names x
and y
, respectively. With dereference path elements, we can obtain a var handle which accesses the y
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 = ...
int rect_y_4 = (int) rectPointYs.get(rect, 2); // rect.points[2]->y
C_0
, also called the initial layout. Each path element in a layout path can be thought of as a function which updates the current layout C_i-1
to some other layout C_i
. That is, for each path element E1, E2, ... En
, in a layout path P
, we compute C_i = f_i(C_i-1)
, where f_i
is the selection function associated with the path element under consideration, denoted as E_i
. The final layout C_i
is also called the selected layout. A layout path P
is considered well-formed for an initial layout C_0
if all its path elements E1, E2, ... En
are well-formed for their corresponding input layouts C_0, C_1, ... C_n-1
. A path element E
is considered well-formed for a layout L
if any of the following is true:
L
is a sequence layout and E
is a sequence path element (one of MemoryLayout.PathElement.sequenceElement(long)
PREVIEW, MemoryLayout.PathElement.sequenceElement(long, long)
PREVIEW or MemoryLayout.PathElement.sequenceElement()
PREVIEW). Moreover, if E
contains one or more sequence indices, such indices have to be compatible with the sequence layout's element count;L
is a group layout and E
is a group path element (one of MemoryLayout.PathElement.groupElement(String)
PREVIEW or MemoryLayout.PathElement.groupElement(long)
PREVIEW). Moreover, the group path element must refer to a valid member layout in L
, either by name, or index;L
is an address layout and E
is a dereference path elementPREVIEW. Moreover, L
must define some target layoutPREVIEW.P
that is not well-formed for an initial layout C_0
will result in an IllegalArgumentException
.Modifier and Type | Interface | Description |
---|---|---|
static interface |
MemoryLayout.PathElementPREVIEW |
Preview. An element in a layout path. |
Modifier and Type | Method | Description |
---|---|---|
long |
byteAlignment() |
Returns the alignment constraint associated with this layout, expressed in bytes. |
default long |
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. |
default MethodHandle |
byteOffsetHandle |
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. |
long |
byteSize() |
Returns the layout size, in bytes. |
boolean |
equals |
Compares the specified object with this layout for equality. |
int |
hashCode() |
Returns the hash code value for this layout. |
Optional |
name() |
Returns the name (if any) associated with this layout. |
static PaddingLayoutPREVIEW |
paddingLayout |
Creates a padding layout with the given byte size. |
default MemoryLayoutPREVIEW |
select |
Returns the layout selected from the provided path, where the initial layout in the path is this layout. |
static SequenceLayoutPREVIEW |
sequenceLayout |
Creates a sequence layout with the given element layout and element count. |
static SequenceLayoutPREVIEW |
sequenceLayout |
Creates a sequence layout with the given element layout and the maximum element count such that it does not overflow a long . |
default MethodHandle |
sliceHandle |
|
static StructLayoutPREVIEW |
structLayout |
Creates a struct layout with the given member layouts. |
String |
toString() |
Returns the string representation of this layout. |
static UnionLayoutPREVIEW |
unionLayout |
Creates a union layout with the given member layouts. |
default VarHandle |
varHandle |
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. |
MemoryLayoutPREVIEW |
withByteAlignment |
Returns a memory layout with the same characteristics as this layout, but with the given alignment constraint (in bytes). |
MemoryLayoutPREVIEW |
withName |
Returns a memory layout with the same characteristics as this layout, but with the given name. |
MemoryLayoutPREVIEW |
withoutName() |
Returns a memory layout with the same characteristics as this layout, but with no name. |
long byteSize()
Optional<String> name()
MemoryLayoutPREVIEW withName(String name)
name
- the layout name.MemoryLayoutPREVIEW withoutName()
long byteAlignment()
A
which is the byte-wise alignment of the layout, where A
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).withByteAlignment(long)
), then this method returns the natural alignment constraint (in bytes) associated with this layout.MemoryLayoutPREVIEW withByteAlignment(long byteAlignment)
byteAlignment
- the layout alignment constraint, expressed in bytes.IllegalArgumentException
- if byteAlignment
is not a power of two.default long byteOffset(MemoryLayout.PathElementPREVIEW... elements)
elements
- the layout path elements.elements
.IllegalArgumentException
- if the layout path is not well-formed for this layout.IllegalArgumentException
- if the layout path contains one or more open path elements.IllegalArgumentException
- if the layout path contains one or more dereference path elements.default MethodHandle byteOffsetHandle(MemoryLayout.PathElementPREVIEW... elements)
The returned method handle has the following characteristics:
long
;long
, one for each open 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 = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
x_1
, x_2
, ... x_n
are dynamic values provided as long
arguments, whereas c_1
, c_2
, ... c_m
are static offset constants and s_0
, s_1
, ... s_n
are static stride constants which are derived from the layout path.byteOffset(PathElement...)
, but more flexibly, as some indices can be specified when invoking the method handle.elements
- the layout path elements.IllegalArgumentException
- if the layout path is not well-formed for this layout.IllegalArgumentException
- if the layout path contains one or more dereference path elements.default VarHandle varHandle(MemoryLayout.PathElementPREVIEW... elements)
The returned var handle has the following characteristics:
long
, one for each open path element in the provided layout path. The order of these access coordinates corresponds to the order in which the open path elements occur in the provided layout path. The final address accessed by the returned var handle can be computed as follows:
Whereaddress = base(segment) + offset
base(segment)
denotes a function that returns the physical base address of the accessed memory segment. For native segments, this function just returns the native segment's addressPREVIEW. For heap segments, this function is more complex, as the address of heap segments is virtualized. The offset
value can be expressed in the following form: whereoffset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
x_1
, x_2
, ... x_n
are dynamic values provided as long
arguments, whereas c_1
, c_2
, ... c_m
are static offset constants and s_1
, s_2
, ... s_n
are static stride constants which are derived from the layout path. Additionally, the provided dynamic values must conform to bounds which are derived from the layout path, that is, 0 <= x_i < b_i
, where 1 <= i <= n
, or IndexOutOfBoundsException
is thrown.
The base address must be aligned according to the alignment constraint of the root layout (this layout). Note that this can be more strict (but not less) than the alignment constraint of the selected value layout.
Multiple paths can be chained, with dereference path elements. A dereference path element constructs a fresh native memory segment whose base address is the address value read obtained by accessing a memory segment at the offset determined by the layout path elements immediately preceding the dereference path element. In other words, if a layout path contains one or more dereference path elements, the final address accessed by the returned var handle can be computed as follows:
whereaddress_1 = base(segment) + offset_1 address_2 = base(segment_1) + offset_2 ... address_k = base(segment_k-1) + offset_k
k
is the number of dereference path elements in a layout path, segment
is the input segment, segment_1
, ... segment_k-1
are the segments obtained by dereferencing the address associated with a given dereference path element (e.g. segment_1
is a native segment whose base address is address_1
), and offset_1
, offset_2
, ... offset_k
are the offsets computed by evaluating the path elements after a given dereference operation (these offsets are obtained using the computation described above). In these more complex access operations, all memory accesses immediately preceding a dereference operation (e.g. those at addresses address_1
, address_2
, ..., address_k-1
are performed using the VarHandle.AccessMode.GET
access mode.elements
- the layout path elements.IllegalArgumentException
- if the layout path is not well-formed for this layout.IllegalArgumentException
- if the layout selected by the provided path is not a value layoutPREVIEW.default MethodHandle sliceHandle(MemoryLayout.PathElementPREVIEW... elements)
The returned method handle has the following characteristics:
MemorySegment
;MemorySegment
, corresponding to the memory segment to be sliced;long
, one for each open 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 of the returned segment is computed as follows:
long offset = byteOffset(elements);
long size = select(elements).byteSize();
MemorySegment slice = segment.asSlice(offset, size);
The segment to be sliced must be aligned according to the alignment constraint of the root layout (this layout). Note that this can be more strict (but not less) than the alignment constraint of the selected value layout.
MemorySegment.asSlice(long, long)
PREVIEW, but more flexibly, as some indices can be specified when invoking the method handle.elements
- the layout path elements.IllegalArgumentException
- if the layout path is not well-formed for this layout.IllegalArgumentException
- if the layout path contains one or more dereference path elements.default MemoryLayoutPREVIEW select(MemoryLayout.PathElementPREVIEW... elements)
elements
- the layout path elements.elements
.IllegalArgumentException
- if the layout path is not well-formed for this layout.IllegalArgumentException
- if the layout path contains one or more dereference path elements.IllegalArgumentException
- if the layout path contains one or more path elements that select one or more sequence element indices, such as MemoryLayout.PathElement.sequenceElement(long)
PREVIEW and MemoryLayout.PathElement.sequenceElement(long, long)
PREVIEW).boolean equals(Object other)
true
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: SequenceLayout.elementCount()
PREVIEW), and if their element layouts (see SequenceLayout.elementLayout()
PREVIEW) are also equal;StructLayout
PREVIEW, UnionLayout
PREVIEW) and if their member layouts (see GroupLayout.memberLayouts()
PREVIEW) are also equal.int hashCode()
String toString()
static PaddingLayoutPREVIEW paddingLayout(long byteSize)
byteSize
- the padding size (expressed in bytes).IllegalArgumentException
- if byteSize <= 0
.static SequenceLayoutPREVIEW sequenceLayout(long elementCount, MemoryLayoutPREVIEW elementLayout)
elementCount
- the sequence element count.elementLayout
- the sequence element layout.IllegalArgumentException
- if elementCount
is negative.IllegalArgumentException
- if elementLayout.byteSize() * elementCount
overflows.IllegalArgumentException
- if elementLayout.byteSize() % elementLayout.byteAlignment() != 0
.static SequenceLayoutPREVIEW sequenceLayout(MemoryLayoutPREVIEW elementLayout)
long
. This is equivalent to the following code: sequenceLayout(Long.MAX_VALUE / elementLayout.byteSize(), elementLayout);
elementLayout
- the sequence element layout.IllegalArgumentException
- if elementLayout.byteSize() % elementLayout.byteAlignment() != 0
.static StructLayoutPREVIEW structLayout(MemoryLayoutPREVIEW... elements)
structLayout(JAVA_SHORT, JAVA_INT);
structLayout(JAVA_SHORT, MemoryLayout.paddingLayout(2), JAVA_INT);
structLayout(JAVA_SHORT, JAVA_INT.withByteAlignment(2));
elements
- The member layouts of the struct layout.IllegalArgumentException
- if the sum of the byte sizes of the member layouts overflows.IllegalArgumentException
- if a member layout in elements
occurs at an offset (relative to the start of the struct layout) which is not compatible with its alignment constraint.static UnionLayoutPREVIEW unionLayout(MemoryLayoutPREVIEW... elements)
elements
- The member layouts of the union layout.
© 1993, 2023, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/foreign/MemoryLayout.html
MemoryLayout
when preview features are enabled.