模块 java.base

接口 MemoryLayout

所有已知的子接口:
GroupLayoutPREVIEW , PaddingLayoutPREVIEW , SequenceLayoutPREVIEW , StructLayoutPREVIEW , UnionLayoutPREVIEW , ValueLayoutPREVIEW , ValueLayout.OfAddressPREVIEW , ValueLayout.OfBooleanPREVIEW , ValueLayout.OfBytePREVIEW , ValueLayout.OfCharPREVIEW , ValueLayout.OfDoublePREVIEW , ValueLayout.OfFloatPREVIEW , ValueLayout.OfIntPREVIEW , ValueLayout.OfLongPREVIEW , ValueLayout.OfShortPREVIEW

public sealed interface MemoryLayout permits SequenceLayout PREVIEW , GroupLayout PREVIEW , PaddingLayout PREVIEW , ValueLayout PREVIEW
MemoryLayout 是 Java 平台的预览 API。
程序只能在启用预览功能时使用 MemoryLayout
预览功能可能会在未来的版本中删除,或升级为 Java 平台的永久功能。
内存布局描述了内存段的内容。布局层次结构中有两个叶节点 value layouts ,用于表示给定大小和种类的值(参见 ValueLayout PREVIEW ) 和 padding layouts ,顾名思义,它们用于表示内存段的一部分,其内容应被忽略,并且主要出于对齐原因而存在(参见 paddingLayout(long) )。 ValueLayout 中定义了一些常用值布局常量PREVIEW 类。

更复杂的布局可以从更简单的布局中派生出来:a sequence layout 表示一个或多个元素布局的重复(参见 SequenceLayout PREVIEW ); group layout 表示(通常)异构成员布局的聚合(参见 GroupLayout PREVIEW ).

布局可以选择与 name 相关联。构造layout paths 时可以参考布局名称。

考虑以下 C 中的结构声明:

typedef struct {
  char kind;
  int value;
} TaggedValues[5];
 
上面的声明可以使用布局对象建模,如下所示:
SequenceLayout taggedValues = MemoryLayout.sequenceLayout(5,
  MemoryLayout.structLayout(
    ValueLayout.JAVA_BYTE.withName("kind"),
    MemoryLayout.paddingLayout(24),
    ValueLayout.JAVA_INT.withName("value")
  )
).withName("TaggedValues");
 

大小、对齐和字节顺序

所有布局都有尺寸;值和填充布局的布局大小始终明确表示;这意味着无论在哪个平台上使用,布局描述总是具有相同的位大小。对于派生布局,大小计算如下:
  • 对于元素布局为E且大小为L的序列布局SS的大小是E的大小乘以L
  • 对于具有成员布局 M1M2、...Mn 的组布局 G,其大小分别为 S1S2、...SnG 的大小为 S1 + S2 + ... + Snmax(S1, S2, ... Sn) 取决于组是 struct 还是 union , 分别

此外,所有布局都有一个 natural alignment 可以推断如下:

  • 对于 padding 布局 L ,自然对齐是 1,不管它的大小;也就是说,在没有显式对齐约束的情况下,填充布局不应影响它嵌套到的组布局的对齐约束
  • 对于大小为 N 的值布局 LL 的自然对齐方式为 N
  • 对于元素布局为 E 的序列布局 SS 的自然对齐是 E 的自然对齐
  • 对于组布局 G 和成员布局 M1 , M2 , ... Mn 其对齐方式分别为 A1 , A2 , ... An , G 的自然对齐方式为 max(A1, A2 ... An)
如果需要,可以覆盖布局的自然对齐方式(请参阅 withBitAlignment(long) ),这对于描述超对齐布局很有用。

所有值布局都有一个 explicit 字节顺序(请参阅 ByteOrder ),它是在创建布局时设置的。

布局路径

layout path 源自 root 布局(通常是组布局或序列布局)并终止于嵌套在根布局内的布局 - 这是布局路径中的布局 selected。布局路径通常表示为一个或多个MemoryLayout.PathElement 的序列PREVIEW 实例。

布局路径例如可用于在另一个布局内获取任意嵌套布局的offsets,快速获取与所选布局对应的内存访问句柄,或在另一个布局内获取任意嵌套布局的select

这样的 layout paths 可以使用此类中的方法以编程方式构建。例如,给定如上构造的taggedValues布局实例,我们可以获得first序列元素中名为value的成员布局的偏移量,以位为单位,如下所示:

long valueOffset = taggedValues.bitOffset(PathElement.sequenceElement(0),
                     PathElement.groupElement("value")); // yields 32
 
同样,我们可以选择名为value的成员布局,如下:
MemoryLayout value = taggedValues.select(PathElement.sequenceElement(),
                     PathElement.groupElement("value"));
 
布局路径可以包含一个或多个 free dimensions 。例如,遍历未指定序列元素的布局路径(即其中一个路径组件是通过 MemoryLayout.PathElement.sequenceElement() 获得的)PREVIEW 方法)具有额外的自由维度,必须在运行时绑定。这在获得 内存段视图 var 句柄 时很重要PREVIEW 来自布局,如以下代码所示:
VarHandle valueHandle = taggedValues.varHandle(PathElement.sequenceElement(),
                        PathElement.groupElement("value"));
 
由于在上面的示例中构建的布局路径恰好具有一个自由维度(因为它没有指定名为valuewhich成员布局应该从封闭序列布局中选择),因此var句柄valueHandle将具有additionallong访问坐标.

具有自由尺寸的布局路径也可用于创建偏移计算方法句柄,使用 bitOffset(PathElement...) byteOffsetHandle(PathElement...) 方法。同样,自由维度被转换为创建的方法句柄的long参数。通过在调用方法句柄时提供这些索引,方法句柄可用于计算序列元素在不同索引处的偏移量。例如:

MethodHandle offsetHandle = taggedValues.byteOffsetHandle(PathElement.sequenceElement(),
                             PathElement.groupElement("kind"));
long offset1 = (long) offsetHandle.invokeExact(1L); // 8
long offset2 = (long) offsetHandle.invokeExact(2L); // 16
 
实现要求:
此接口的实现是不可变的、线程安全的和 value-based
密封类层次结构图:
Sealed class hierarchy graph for MemoryLayoutSealed class hierarchy graph for MemoryLayout
自从:
19
  • 方法详情

    • bitSize

      long bitSize()
      返回布局大小,以位为单位。
      返回:
      布局大小,以位为单位
    • byteSize

      long byteSize()
      返回布局大小,以字节为单位。
      返回:
      布局大小,以字节为单位
      抛出:
      UnsupportedOperationException - 如果 bitSize() 不是 8 的倍数。
    • name

      Optional <String > name()
      返回与此布局关联的名称(如果有)。
      返回:
      与此布局关联的名称(如果有)
      参见:
    • withName

      MemoryLayout PREVIEW  withName(String  name)
      返回与此布局具有相同大小和对齐约束但具有指定名称的相同类型的内存布局。
      参数:
      name - 布局名称。
      返回:
      具有给定名称的内存布局。
      参见:
    • bitAlignment

      long bitAlignment()
      返回与此布局关联的对齐约束,以位表示。布局对齐定义了 2 的幂 A,这是布局的逐位对齐。如果 A <= 8 那么 A/8 是正确指向此布局的任何指针必须对齐的字节数。因此:
      • A=8表示unaligned(通常意义上的),这在数据包中很常见。
      • A=64 表示字对齐(在 LP64 上),A=32 int 对齐,A=16 short 对齐等。
      • A=512 是 x86/SV ABI(对于 AVX-512 数据)要求的最严格对齐。
      如果未在此布局上设置显式对齐约束(请参阅 withBitAlignment(long) ),则此方法返回与此布局关联的 自然排列 约束(以位为单位)。
      返回:
      布局对齐约束,以位为单位。
    • byteAlignment

      default long byteAlignment()
      返回与此布局关联的对齐约束,以字节表示。布局对齐定义了 2 的幂 A,这是布局的字节对齐方式,其中 A 是正确指向此布局的任何指针必须对齐的字节数。因此:
      • A=1表示unaligned(通常意义上的),这在数据包中很常见。
      • A=8 表示字对齐(在 LP64 上),A=4 int 对齐,A=2 short 对齐等。
      • A=64 是 x86/SV ABI(用于 AVX-512 数据)要求的最严格对齐。
      如果未在此布局上设置显式对齐约束(请参阅 withBitAlignment(long) ),则此方法返回与此布局关联的 自然排列 约束(以字节为单位)。
      返回:
      布局对齐约束,以字节为单位。
      抛出:
      UnsupportedOperationException - 如果 bitAlignment() 不是 8 的倍数。
    • withBitAlignment

      MemoryLayout PREVIEW  withBitAlignment(long bitAlignment)
      返回与此布局具有相同大小和名称但具有指定对齐约束(以位为单位)的相同类型的内存布局。
      参数:
      bitAlignment - 布局对齐约束,以位表示。
      返回:
      具有给定对齐约束的内存布局。
      抛出:
      IllegalArgumentException - 如果 bitAlignment 不是 2 的幂,或者小于 8。
    • bitOffset

      default long bitOffset(MemoryLayout.PathElement PREVIEW ... elements)
      计算给定布局路径选择的布局的偏移量(以位为单位),其中该路径被认为是此布局的根。
      参数:
      elements - 布局路径元素。
      返回:
      elements 中的布局路径选择的布局的偏移量(以位为单位)。
      抛出:
      IllegalArgumentException - 如果布局路径没有选择嵌套在该布局中的任何布局,或者如果布局路径包含一个或多个选择多个序列元素索引的路径元素(参见 MemoryLayout.PathElement.sequenceElement() PREVIEW MemoryLayout.PathElement.sequenceElement(long, long) PREVIEW ).
      NullPointerException - 如果 elements == null ,或者 elements 中的任何元素是 null
    • bitOffsetHandle

      default MethodHandle  bitOffsetHandle(MemoryLayout.PathElement PREVIEW ... elements)
      创建一个方法句柄,可用于计算给定布局路径选择的布局的偏移量(以位为单位),其中该路径被视为植根于此布局。

      返回的方法句柄的返回类型为 long ,并且具有与提供的布局路径中的自由维度一样多的 long 参数类型(参见 MemoryLayout.PathElement.sequenceElement() PREVIEW ), 其中参数的顺序对应于路径元素的顺序。返回的方法句柄可用于计算类似于 bitOffset(PathElement...) 的布局偏移量,但其中某些序列索引仅在调用方法句柄时指定。

      方法句柄返回的最终偏移量计算如下:

      
       offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
        
      其中 x_1x_2 、... x_n 是作为 long 参数提供的 dynamic 值,而 c_1c_2 、 ... c_mstatic 偏移常量和 s_0 , s_1 , ... s_nstatic 步幅常数,它们源自布局路径.
      参数:
      elements - 布局路径元素。
      返回:
      一个方法句柄,可用于计算给定布局路径元素指定的布局元素的位偏移,当提供缺少的序列元素索引时。
      抛出:
      IllegalArgumentException - 如果布局路径包含一个或多个选择多个序列元素索引的路径元素(参见 MemoryLayout.PathElement.sequenceElement(long, long) PREVIEW ).
    • byteOffset

      default long byteOffset(MemoryLayout.PathElement PREVIEW ... elements)
      计算给定布局路径选择的布局的偏移量(以字节为单位),其中该路径被认为是此布局的根。
      参数:
      elements - 布局路径元素。
      返回:
      elements 中的布局路径选择的布局的偏移量(以字节为单位)。
      抛出:
      IllegalArgumentException - 如果布局路径没有选择嵌套在该布局中的任何布局,或者如果布局路径包含一个或多个选择多个序列元素索引的路径元素(参见 MemoryLayout.PathElement.sequenceElement() PREVIEW MemoryLayout.PathElement.sequenceElement(long, long) PREVIEW ).
      UnsupportedOperationException - 如果 bitOffset(elements) 不是 8 的倍数。
      NullPointerException - 如果 elements == null ,或者 elements 中的任何元素是 null
    • byteOffsetHandle

      default MethodHandle  byteOffsetHandle(MemoryLayout.PathElement PREVIEW ... elements)
      创建一个方法句柄,该句柄可用于计算给定布局路径选择的布局的偏移量(以字节为单位),其中该路径被视为植根于此布局。

      返回的方法句柄的返回类型为 long ,并且具有与提供的布局路径中的自由维度一样多的 long 参数类型(参见 MemoryLayout.PathElement.sequenceElement() PREVIEW ), 其中参数的顺序对应于路径元素的顺序。返回的方法句柄可用于计算类似于 byteOffset(PathElement...) 的布局偏移量,但其中一些序列索引仅在调用方法句柄时指定。

      方法句柄返回的最终偏移量计算如下:

      
       bitOffset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
       offset = bitOffset / 8
        
      其中 x_1x_2 、... x_n 是作为 long 参数提供的 dynamic 值,而 c_1c_2 、 ... c_mstatic 偏移常量和 s_0 , s_1 , ... s_nstatic 步幅常数,它们源自布局路径.

      如果以位计算的偏移量不是 8 的倍数,则方法句柄将抛出 UnsupportedOperationException

      参数:
      elements - 布局路径元素。
      返回:
      一个方法句柄,可用于计算给定布局路径元素指定的布局元素的字节偏移量,当提供缺少的序列元素索引时。
      抛出:
      IllegalArgumentException - 如果布局路径包含一个或多个选择多个序列元素索引的路径元素(参见 MemoryLayout.PathElement.sequenceElement(long, long) PREVIEW ).
    • varHandle

      default VarHandle  varHandle(MemoryLayout.PathElement PREVIEW ... elements)
      创建一个 var 句柄,该句柄可用于访问给定布局路径选择的布局中的内存段,其中该路径被认为植根于此布局。

      返回的 var 句柄访问的最终地址可以计算如下:

      
       address = base(segment) + offset
        
      其中base(segment)表示返回访问内存段物理基地址的函数。对于本机段,此函数仅返回本机段的 addressPREVIEW .对于堆段,这个函数更复杂,因为堆段的地址是虚拟化的。 offset坐标可以用以下形式表示:
      
       offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
        
      其中 x_1x_2 、... x_n 是作为 long 参数提供的 dynamic 值,而 c_1c_2 、 ... c_mstatic 偏移常量和 s_1 , s_2 , ... s_nstatic 步幅常数,它们源自布局路径.

      此外,提供的动态值必须符合从布局路径派生的某些边界,即 0 <= x_i < b_i ,其中抛出 1 <= i <= nIndexOutOfBoundsException

      API 注意:
      生成的 var 句柄将为该布局路径中包含的每个未指定的序列访问组件提供一个额外的 long 访问坐标。此外,生成的 var 句柄具有某些 access mode restrictions ,这是所有内存段视图句柄共有的。
      参数:
      elements - 布局路径元素。
      返回:
      一个 var 句柄,可用于访问由 elements 中的布局路径选择的(可能嵌套的)布局中的内存段。
      抛出:
      UnsupportedOperationException - 如果布局路径中有一个或多个元素具有不兼容的对齐约束。
      IllegalArgumentException - 如果 elements 中的布局路径未选择值布局(请参见 ValueLayout PREVIEW ).
      参见:
    • sliceHandle

      default MethodHandle  sliceHandle(MemoryLayout.PathElement PREVIEW ... elements)
      创建一个方法句柄,给定一个内存段,返回一个slicePREVIEW 对应于给定布局路径选择的布局,其中该路径被认为植根于此布局。

      返回的方法句柄的返回类型为 MemorySegment ,以 MemorySegment 参数作为表示要切片的段的前导参数,并具有与提供的布局路径中的自由维度一样多的尾随 long 参数类型(参见 MemoryLayout.PathElement.sequenceElement() PREVIEW ), 其中参数的顺序对应于路径元素的顺序。返回的方法句柄可用于创建类似于使用 MemorySegment.asSlice(long, long) 的切片PREVIEW ,但是偏移量参数是根据调用方法句柄时指定的索引动态计算的。

      返回段的偏移量计算如下:

      
       bitOffset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
       offset = bitOffset / 8
        
      其中 x_1x_2 、... x_n 是作为 long 参数提供的 dynamic 值,而 c_1c_2 、 ... c_mstatic 偏移常量和 s_1 , s_2 , ... s_nstatic 步幅常数,它们源自布局路径.

      计算偏移量后,返回的段就好像通过调用创建:

      segment.asSlice(offset, layout.byteSize());
       
      其中 segment 是要切片的段,其中 layout 是由给定布局路径选择的布局,根据 select(PathElement...)

      如果以位计算的偏移量不是 8 的倍数,则方法句柄将抛出 UnsupportedOperationException

      参数:
      elements - 布局路径元素。
      返回:
      一个方法句柄,可用于在给定段的情况下创建所选布局元素的切片。
      抛出:
      UnsupportedOperationException - 如果所选布局的大小(以位为单位)不是 8 的倍数。
    • select

      default MemoryLayout PREVIEW  select(MemoryLayout.PathElement PREVIEW ... elements)
      从以该布局为根的路径中选择布局。
      参数:
      elements - 布局路径元素。
      返回:
      elements 中的布局路径选择的布局。
      抛出:
      IllegalArgumentException - 如果布局路径没有选择嵌套在该布局中的任何布局,或者如果布局路径包含一个或多个选择一个或多个序列元素索引的路径元素(参见 MemoryLayout.PathElement.sequenceElement(long) PREVIEW MemoryLayout.PathElement.sequenceElement(long, long) PREVIEW ).
    • equals

      boolean equals(Object  other)
      比较指定对象与此布局是否相等。返回 true 当且仅当指定的对象也是一个布局,并且它等于这个布局。如果两个布局属于同一类型,具有相同的大小、名称和对齐约束,则它们被认为是相等的。此外,根据布局类型,还必须满足其他条件:
      重写:
      equals 在类 Object
      参数:
      other - 要与此布局进行相等比较的对象。
      返回:
      true 如果指定对象等于此布局。
      参见:
    • hashCode

      int hashCode()
      返回此布局的哈希码值。
      重写:
      hashCode 在类 Object
      返回:
      此布局的哈希码值
      参见:
    • toString

      String  toString()
      返回此布局的字符串表示形式。
      重写:
      toString 在类 Object
      返回:
      此布局的字符串表示形式
    • paddingLayout

      static PaddingLayout PREVIEW  paddingLayout(long size)
      创建具有给定大小的填充布局。
      参数:
      size - 以位为单位的填充大小。
      返回:
      新的选择器布局。
      抛出:
      IllegalArgumentException - 如果 size <= 0
    • valueLayout

      static ValueLayout PREVIEW  valueLayout(Class <?> carrier, ByteOrder  order)
      创建给定 Java 载体和字节顺序的值布局。结果值布局的类型由提供的载体决定:
      参数:
      carrier - 值布局载体。
      order - 值布局的字节顺序。
      返回:
      具有给定 Java 载体和字节顺序的值布局。
      抛出:
      IllegalArgumentException - 如果运营商类型不受支持。
    • sequenceLayout

      static SequenceLayout PREVIEW  sequenceLayout(long elementCount, MemoryLayout PREVIEW  elementLayout)
      使用给定的元素布局和元素计数创建序列布局。
      参数:
      elementCount - 序列元素计数。
      elementLayout - 序列元素布局。
      返回:
      具有给定元素布局和大小的新序列布局。
      抛出:
      IllegalArgumentException - 如果 elementCount 为负。
    • sequenceLayout

      static SequenceLayout PREVIEW  sequenceLayout(MemoryLayout PREVIEW  elementLayout)
      使用给定的元素布局和最大元素数创建序列布局,使其不会溢出 long 。这等效于以下代码:
      sequenceLayout(Long.MAX_VALUE / elementLayout.bitSize(), elementLayout);
       
      参数:
      elementLayout - 序列元素布局。
      返回:
      具有给定元素布局和最大元素数的新序列布局。
    • structLayout

      static StructLayout PREVIEW  structLayout(MemoryLayout PREVIEW ... elements)
      使用给定的成员布局创建结构布局。
      参数:
      elements - 结构布局的成员布局。
      返回:
      具有给定成员布局的结构布局。
      抛出:
      IllegalArgumentException - 如果成员布局的 位大小 总和溢出。
    • unionLayout

      static UnionLayout PREVIEW  unionLayout(MemoryLayout PREVIEW ... elements)
      使用给定的成员布局创建联合布局。
      参数:
      elements - 联合布局的成员布局。
      返回:
      具有给定成员布局的联合布局。