Module java.base

Interface MemorySegment


public sealed interface MemorySegment
MemorySegment是Java平台的预览API。
仅当启用预览功能时,程序才能使用MemorySegment
预览功能可能会在未来的版本中被移除,或升级为Java平台的永久功能。
内存段提供对内存连续区域的访问。

有两种类型的内存段:

  • 一个堆段由Java堆内的内存区域支持,并提供对其的访问(一个“堆内”区域)。
  • 一个本地段由Java堆外的内存区域支持,并提供对其的访问(一个“堆外”区域)。
可以通过调用其中一个ofArray(int[])工厂方法来获取堆段。这些方法返回一个由持有指定Java数组的堆内区域支持的内存段。

可以通过调用一个Arena.allocate(long, long)预览工厂方法来获取本地段,该方法返回一个由给定大小分配并对齐到给定对齐约束的堆外区域支持的内存段。另外,本地段也可以通过mapping预览文件到一个新的堆外区域来获取(在某些系统中,此操作有时被称为mmap)。以这种方式获取的段称为映射段,它们的内容可以被持久化加载到底层内存映射文件中。

两种类型的段都使用相同的方法进行读写,称为访问操作。对内存段的访问操作始终且仅提供对获取该段的区域的访问。

内存段的特征

每个内存段都有一个地址,表示为一个long值。段的地址的性质取决于段的类型:
  • 堆段的地址不是物理地址,而是内存区域的偏移量,该区域支持段。该区域位于Java堆内部,因此垃圾回收可能导致该区域随着时间在物理内存中重新定位,但这不会暴露给MemorySegment API的客户端,他们看到由该区域支持的堆段的稳定虚拟化地址。通过其中一个ofArray(int[])工厂方法获取的堆段的地址为零。
  • 本地段(包括映射段)的地址表示支持段的内存区域的物理地址。

每个内存段都有一个大小。堆段的大小是从获取它的Java数组派生的。这个大小在Java运行时中是可预测的。本地段的大小可以显式传递(如在Arena.allocate(long, long)预览中)或从MemoryLayout预览派生(如在SegmentAllocator.allocate(MemoryLayout)预览中)。内存段的大小通常是一个正数,但可能是,但永远不会是负数。

内存段的地址和大小共同确保对段的访问操作不会超出支持段的内存区域的边界。也就是说,内存段具有空间边界

每个内存段都与一个作用域预览相关联。这确保了在支持内存段的内存区域不再可用时(例如,在与访问的内存段关联的作用域不再活动预览后),对内存段的访问操作不会发生。也就是说,内存段具有时间边界

最后,对内存段的访问操作可能受到额外的线程约束检查。堆段可以从任何线程访问。相反,本地段只能与用于获取它们的arena的约束特性兼容地访问。

访问内存段

可以使用此类中提供的各种访问操作来读取或写入内存段(例如get(ValueLayout.OfInt, long))。每个访问操作都需要一个值布局预览,指定值的大小和形状,以及一个以字节为单位的偏移量。例如,要从段中读取一个int值,使用默认字节顺序,可以使用以下代码:
MemorySegment segment = ...
int value = segment.get(ValueLayout.JAVA_INT, 0);
如果要读取的值是使用大端编码存储在内存中的,访问操作可以表示如下:
MemorySegment segment = ...
int value = segment.get(ValueLayout.JAVA_INT.withOrder(BIG_ENDIAN), 0);
对于更复杂的访问操作(例如结构化内存访问),客户端可以获取一个var handle预览,该var handle接受一个段和一个long偏移量。可以通过在MethodHandles类中定义的var handle组合函数中适应段var handle视图来获取更复杂的var handle:
MemorySegment segment = ...
VarHandle intHandle = MethodHandles.memorySegmentViewVarHandle(ValueLayout.JAVA_INT);
MethodHandle multiplyExact = MethodHandles.lookup()
                                          .findStatic(Math.class, "multiplyExact",
                                                                  MethodType.methodType(long.class, long.class, long.class));
intHandle = MethodHandles.filterCoordinates(intHandle, 1,
                                            MethodHandles.insertArguments(multiplyExact, 0, ValueLayout.JAVA_INT.byteSize()));
int value = (int) intHandle.get(segment, 3L); // 获取偏移量为3 * 4 = 12的int元素
另外,可以通过提供所谓的布局路径内存布局预览中获取复杂的var handle:
MemorySegment segment = ...
VarHandle intHandle = ValueLayout.JAVA_INT.arrayElementVarHandle();
int value = (int) intHandle.get(segment, 3L); // 获取偏移量为3 * 4 = 12的int元素

切片内存段

内存段支持切片。切片一个内存段会返回一个由原始内存段支持的相同内存区域的新内存段。切片段的地址是从原始段的地址派生的,通过添加一个偏移量(以字节表示)。切片段的大小可以隐式派生(通过从原始段的大小中减去指定的偏移量),或者显式提供。换句话说,切片段比原始段具有更严格的空间边界:
 Arena arena = ...
 MemorySegment segment = arena.allocate(100);
 MemorySegment slice = segment.asSlice(50, 10);
 slice.get(ValueLayout.JAVA_INT, 20); // 越界!
 arena.close();
 slice.get(ValueLayout.JAVA_INT, 0); // 已关闭!
上述代码创建了一个长度为100字节的本地段;然后,它创建了一个从segment的偏移量50开始,长度为10字节的切片。也就是说,slice的地址是segment.address() + 50,其大小为10。因此,尝试在slice段的偏移量20处读取int值将导致异常。原始段的时间边界预览被其切片继承;也就是说,当与segment关联的作用域不再活动预览时,slice也将变得不可访问。

客户端可以从一个段中获取一个Stream,然后可以用于切割该段(根据给定的元素布局),甚至允许多个线程并行在不同的段切片上工作(为了实现这一点,该段必须可以从多个线程中访问)。以下代码可用于并行求和内存段中所有int值:

 try (Arena arena = Arena.ofShared()) {
     SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT);
     MemorySegment segment = arena.allocate(SEQUENCE_LAYOUT);
     int sum = segment.elements(ValueLayout.JAVA_INT).parallel()
                      .mapToInt(s -> s.get(ValueLayout.JAVA_INT, 0))
                      .sum();
 }

对齐

对内存段的访问操作不仅受到段的空间和时间限制的约束,还受到操作指定的值布局的对齐约束的限制。访问操作只能访问段中那些根据布局对齐的物理内存地址的偏移量。物理内存中的地址根据布局对齐,如果地址是布局对齐约束的整数倍。例如,地址1000根据8字节对齐约束对齐(因为1000是8的整数倍),也根据4字节对齐约束对齐,以及2字节对齐约束对齐;相比之下,地址1004根据4字节对齐约束对齐,以及2字节对齐约束对齐,但不根据8字节对齐约束对齐。访问操作需要遵守对齐约束,因为它会影响访问操作的性能,并且还可以确定在给定物理地址上哪些访问操作是可用的。例如,使用原子访问操作需要在对齐地址上执行。此外,对齐适用于访问操作,无论被访问的段是本机段还是堆段。

如果被访问的段是本机段,则其在物理内存中的地址可以与偏移量结合以获取物理内存中的目标地址。下面的伪函数演示了这一点:

boolean isAligned(MemorySegment segment, long offset, MemoryLayout layout) {
  return ((segment.address() + offset) % layout.byteAlignment()) == 0;
}
例如:
  • 一个地址为1000的本机段可以在8字节对齐约束下访问偏移量为0、8、16、24等,因为目标地址(1000、1008、1016、1024)是8字节对齐的。在1-7或9-15或17-23的偏移量处的访问是不允许的,因为目标地址不会是8字节对齐的。
  • 一个地址为1000的本机段可以在4字节对齐约束下访问偏移量为0、4、8、12等,因为目标地址(1000、1004、1008、1012)是4字节对齐的。在1-3或5-7或9-11的偏移量处的访问是不允许的,因为目标地址不会是4字节对齐的。
  • 一个地址为1000的本机段可以在2字节对齐约束下访问偏移量为0、2、4、6等,因为目标地址(1000、1002、1004、1006)是2字节对齐的。在1或3或5的偏移量处的访问是不允许的,因为目标地址不会是2字节对齐的。
  • 一个地址为1004的本机段可以在4字节对齐约束下访问偏移量为0、4、8、12等,以及在2字节对齐约束下访问偏移量为0、2、4、6等。在8字节对齐约束下,它可以在偏移量为4、12、20、28等处访问。
  • 一个地址为1006的本机段可以在2字节对齐约束下访问偏移量为0、2、4、6等。在4字节对齐约束下,它可以在偏移量为2、6、10、14等处访问。在8字节对齐约束下,它可以在偏移量为2、10、18、26等处访问。
  • 一个地址为1007的本机段可以在1字节对齐约束下访问偏移量为0、1、2、3等。在2字节对齐约束下,它可以在偏移量为1、3、5、7等处访问。在4字节对齐约束下,它可以在偏移量为1、5、9、13等处访问。在8字节对齐约束下,它可以在偏移量为1、9、17、25等处访问。

访问段所使用的对齐约束通常由存储在段中的数据结构的形状决定。例如,如果程序员希望在本机段中存储一系列8字节值,则应通过指定8字节对齐约束来分配段,可以通过Arena.allocate(long, long)预览SegmentAllocator.allocate(MemoryLayout)预览来实现。这些工厂确保返回段的堆外内存区域具有起始地址是8字节对齐的。随后,程序员可以在感兴趣的偏移量处访问段,如0、8、16、24等,以确保每次访问都是对齐的。

如果被访问的段是堆段,则确定访问是否对齐更为复杂。堆段在物理内存中的地址是未知的,甚至不是固定的(在垃圾回收期间段可能会被重新定位)。这意味着无法将地址与指定的偏移量结合以确定物理内存中的目标地址。由于对齐约束总是指的是物理内存中地址的对齐,原则上无法确定堆段中任何偏移量是否对齐。例如,假设程序员选择了8字节对齐约束,并尝试在堆段中访问偏移量为16。如果堆段的地址0对应于物理地址1000,则目标地址(1016)将是对齐的,但如果地址0对应于物理地址1004,则目标地址(1020)将不是对齐的。允许访问根据程序员选择的对齐约束对齐的目标地址是不可取的,因为这些地址可能在物理内存中不可预测地对齐(例如,由于平台考虑和/或垃圾回收行为)。

实际上,Java运行时将数组布局在内存中,以便每个n字节元素出现在n字节对齐的物理地址上(除了long[]double[],在这些情况下对齐取决于平台,如下所述)。即使数组在垃圾回收期间重新定位,运行时也会保留此不变性。访问操作依赖于此不变性,以确定堆段中指定偏移量是否指向物理内存中的对齐地址。例如:

  • short[]数组的起始物理地址将是2字节对齐的(例如1006),以便连续的short元素出现在2字节对齐的地址上(例如1006、1008、1010、1012等)。由short[]数组支持的堆段可以在2字节对齐约束下访问偏移量为0、2、4、6等。在4字节对齐约束下,段不能在任何偏移量下访问,因为不能保证目标地址是4字节对齐的,例如,偏移量0对应于物理地址1006,而偏移量1对应于物理地址1007。类似地,在8字节对齐约束下,段也不能在任何偏移量下访问,因为不能保证目标地址是8字节对齐的,例如,偏移量2对应于物理地址1008,但偏移量4对应于物理地址1010。
  • long[]数组的起始物理地址将在64位平台上是8字节对齐的(例如1000),以便连续的long元素出现在8字节对齐的地址上(例如1000、1008、1016、1024等)。在64位平台上,由long[]数组支持的堆段可以在8字节对齐约束下访问偏移量为0、8、16、24等。此外,段可以在4字节对齐约束下访问偏移量为0、4、8、12等,因为目标地址(1000、1004、1008、1012)是4字节对齐的。段还可以在2字节对齐约束下访问偏移量为0、2、4、6等,因为目标地址(例如1000、1002、1004、1006)是2字节对齐的。
  • long[]数组的起始物理地址将在32位平台上是4字节对齐的(例如1004),以便连续的long元素出现在4字节对齐的地址上(例如1004、1008、1012、1016等)。在32位平台上,由long[]数组支持的堆段可以在4字节对齐约束下访问偏移量为0、4、8、12等,因为目标地址(1004、1008、1012、1016)是4字节对齐的。段还可以在2字节对齐约束下访问偏移量为0、2、4、6等,因为目标地址(例如1000、1002、1004、1006)是2字节对齐的。

换句话说,堆段具有一个(依赖于平台的)最大对齐,该对齐是从支持段的Java数组元素的大小派生的,如下表所示:

堆段的最大对齐
数组类型(支持区域) 支持的最大对齐(字节)
boolean[] ValueLayout.JAVA_BOOLEAN.byteAlignment()
byte[] ValueLayout.JAVA_BYTE.byteAlignment()
char[] ValueLayout.JAVA_CHAR.byteAlignment()
short[] ValueLayout.JAVA_SHORT.byteAlignment()
int[] ValueLayout.JAVA_INT.byteAlignment()
float[] ValueLayout.JAVA_FLOAT.byteAlignment()
long[] ValueLayout.JAVA_LONG.byteAlignment()
double[] ValueLayout.JAVA_DOUBLE.byteAlignment()
堆段只能使用对齐小于或等于与堆段关联的最大对齐的布局进行访问。尝试使用对齐大于与堆段关联的最大对齐的布局访问堆段将失败,如下例所示:
MemorySegment byteSegment = MemorySegment.ofArray(new byte[10]);
byteSegment.get(ValueLayout.JAVA_INT, 0); // 失败:ValueLayout.JAVA_INT.byteAlignment() > ValueLayout.JAVA_BYTE.byteAlignment()
在这种情况下,客户端有两个选择。他们可以使用由不同数组类型(例如 long[])支持的堆段,能够支持更大的最大对齐。更具体地说,与 long[] 关联的最大对齐设置为 ValueLayout.JAVA_LONG.byteAlignment(),这是一个平台相关的值(设置为 ValueLayout.ADDRESS.byteSize())。也就是说,long[] 在64位平台上至少提供8字节对齐,但在32位平台上只提供4字节对齐:
MemorySegment longSegment = MemorySegment.ofArray(new long[10]);
longSegment.get(ValueLayout.JAVA_INT, 0); // ok: ValueLayout.JAVA_INT.byteAlignment() <= ValueLayout.JAVA_LONG.byteAlignment()
或者,他们可以使用 非对齐布局 调用访问操作。所有非对齐布局常量(例如 ValueLayout.JAVA_INT_UNALIGNED预览)的对齐约束设置为1:
MemorySegment byteSegment = MemorySegment.ofArray(new byte[10]);
byteSegment.get(ValueLayout.JAVA_INT_UNALIGNED, 0); // ok: ValueLayout.JAVA_INT_UNALIGNED.byteAlignment() == ValueLayout.JAVA_BYTE.byteAlignment()

零长度内存段

当与 外部函数 交互时,这些函数通常会分配一块内存区域并返回指向该区域的指针。使用内存段来模拟内存区域是具有挑战性的,因为Java运行时无法了解区域的大小。只能使用指针中存储的起始地址,而无法了解区域的大小。例如,具有返回类型为 char* 的C函数可能返回指向包含单个 char 值的区域的指针,或者返回指向包含 char 值数组的区域的指针,其中数组的大小可能在单独的参数中提供。对于调用外部函数并希望使用其结果的代码来说,数组的大小并不容易确定。除了无法了解从外部函数返回的指针所指向的内存区域的大小外,还无法了解分配该区域内存的外部函数对该区域内存的预期生命周期。

MemorySegment API使用零长度内存段来表示:

  • 从外部函数返回的指针;
  • 由外部函数传递给上调用存根的指针;以及
  • 从内存段读取的指针(稍后详细介绍)。
零长度段的地址是指针中存储的地址。零长度段的空间和时间边界如下:
  • 段的大小为零。任何尝试访问这些段的操作都将导致 IndexOutOfBoundsException。这是一个至关重要的安全特性:由于这些段与大小未知的内存区域相关联,涉及这些段的任何访问操作都无法验证。实际上,零长度内存段包装了一个地址,没有明确意图的情况下不能使用;
  • 该段与始终存活的新作用域相关联。因此,虽然无法直接访问零长度内存段,但可以将其不透明地传递给其他接受指针的外部函数。

为了演示客户端如何使用零长度内存段,考虑一个想要从某个内存段读取指针的客户端的情况。这可以通过 get(AddressLayout, long) 访问方法完成。该方法接受一个 地址布局预览(例如 ValueLayout.ADDRESS预览),即要读取的指针的布局。例如,在64位平台上,地址布局的大小为8字节。访问操作还接受一个以字节为单位的偏移量,指示存储指针的位置(相对于内存段的起始位置)。访问操作返回一个零长度的本机内存段,其背后是一个内存区域,其起始地址是指定偏移量处读取的64位值。

返回的零长度内存段不能被客户端直接访问:由于段的大小为零,任何访问操作都将导致越界访问。相反,客户端必须通过 reinterpret(long) 方法不安全地为零长度内存段分配新的空间边界。操作如下:

 MemorySegment z = segment.get(ValueLayout.ADDRESS, ...);   // 大小 = 0
 MemorySegment ptr = z.reinterpret(16);                     // 大小 = 16
 int x = ptr.getAtIndex(ValueLayout.JAVA_INT, 3);           // ok

在某些情况下,客户端可能还希望为零长度内存段分配新的时间边界。这可以通过 reinterpret(long, Arena, Consumer) 方法完成,该方法返回一个具有所需大小和与提供的作用域相同时间边界的新本机段:

 MemorySegment ptr = null;
 try (Arena arena = Arena.ofConfined()) {
       MemorySegment z = segment.get(ValueLayout.ADDRESS, ...);    // 大小 = 0, 作用域 = 始终存活
       ptr = z.reinterpret(16, arena, null);                       // 大小 = 4, 作用域 = arena.scope()
       int x = ptr.getAtIndex(ValueLayout.JAVA_INT, 3);            // ok
 }
 int x = ptr.getAtIndex(ValueLayout.JAVA_INT, 3);                  // 抛出IllegalStateException
或者,如果知道零长度内存段背后的内存区域的大小是静态的,客户端可以在读取指针时使用 目标布局预览 覆盖地址布局。然后,目标布局用于动态 扩展访问操作返回的本机内存段的大小,使返回的段不再是零长度内存段,而其表示的指针可以直接解引用:
 AddressLayout intArrPtrLayout = ValueLayout.ADDRESS.withTargetLayout(
         MemoryLayout.sequenceLayout(4, ValueLayout.JAVA_INT)); // 用于 int (*ptr)[4] 的布局
 MemorySegment ptr = segment.get(intArrPtrLayout, ...);         // 大小 = 16
 int x = ptr.getAtIndex(ValueLayout.JAVA_INT, 3);               // ok

所有可用于操作零长度内存段的方法(reinterpret(long)reinterpret(Arena, Consumer)reinterpret(long, Arena, Consumer)AddressLayout.withTargetLayout(MemoryLayout)预览)都是受限制方法,应谨慎使用:分配不正确的空间和/或时间边界可能导致在尝试访问内存段时导致虚拟机崩溃。

实现要求:
此接口的实现是不可变的、线程安全的,并且是基于值的。
自版本:
19
  • Field Details

    • NULL

      static final MemorySegmentPREVIEW NULL
      一个零长度的本机段,模拟了NULL地址。
  • Method Details

    • address

      long address()
      返回此内存段的地址。
      API注释:
      当使用此方法将段地址传递给某些外部操作(例如JNI函数)时,客户端必须确保段在整个操作期间保持可达。如果未能这样做,可能会导致支持内存段的内存区域过早释放,如果段是使用自动竞技场预览分配的。
      返回:
      此内存段的地址
    • heapBase

      Optional<Object> heapBase()
      返回存储在内存段后备的堆内存区域中的Java对象(如果有)。例如,如果此内存段是使用ofArray(byte[])工厂方法创建的堆内存段,则此方法将返回用于获取该段的byte[]对象。如果此段是一个本机段,或者如果此段是只读的,则此方法返回一个空的Optional值。
      返回:
      与此内存段关联的Java对象(如果有)。
    • spliterator

      Spliterator<MemorySegmentPREVIEW> spliterator(MemoryLayoutPREVIEW elementLayout)
      返回此内存段的分割器。返回的分割器报告Spliterator.SIZEDSpliterator.SUBSIZEDSpliterator.IMMUTABLESpliterator.NONNULLSpliterator.ORDERED特征。

      返回的分割器根据指定的元素布局对此段进行分割;也就是说,如果提供的布局大小为N,则调用Spliterator.trySplit()将导致一个大约为S/N元素的分割器(取决于N是偶数还是奇数),其中S是此段的大小。因此,只要S/N >= 2,就可以进行分割。分割器返回的段具有与此段相同的生命周期。

      返回的分割器有效地允许将此段切片为不相交的片段,然后可以由多个线程并行处理。

      参数:
      elementLayout - 用于分割的布局。
      返回:
      此段的元素分割器
      抛出:
      IllegalArgumentException - 如果elementLayout.byteSize() == 0
      IllegalArgumentException - 如果byteSize() % elementLayout.byteSize() != 0
      IllegalArgumentException - 如果elementLayout.byteSize() % elementLayout.byteAlignment() != 0
      IllegalArgumentException - 如果此段与提供的布局中的对齐约束不兼容
    • elements

      Stream<MemorySegmentPREVIEW> elements(MemoryLayoutPREVIEW elementLayout)
      返回此段中与指定布局大小匹配的不相交片段的顺序Stream。调用此方法等效于以下代码:
      StreamSupport.stream(segment.spliterator(elementLayout), false);
      
      参数:
      elementLayout - 用于分割的布局。
      返回:
      在此段中的不相交片段上的顺序Stream
      抛出:
      IllegalArgumentException - 如果elementLayout.byteSize() == 0
      IllegalArgumentException - 如果byteSize() % elementLayout.byteSize() != 0
      IllegalArgumentException - 如果elementLayout.byteSize() % elementLayout.byteAlignment() != 0
      IllegalArgumentException - 如果此段与提供的布局中的对齐约束不兼容
    • scope

      返回与此内存段关联的作用域。
      返回:
      与此内存段关联的作用域
    • isAccessibleBy

      boolean isAccessibleBy(Thread thread)
      如果可以从提供的线程访问此段,则返回true
      参数:
      thread - 要测试的线程。
      返回:
      如果可以从提供的线程访问此段,则返回true
    • byteSize

      long byteSize()
      返回此内存段的大小(以字节为单位)。
      返回:
      此内存段的大小(以字节为单位)
    • asSlice

      MemorySegmentPREVIEW asSlice(long offset, long newSize)
      返回此内存段的一个片段,位于给定偏移量处。返回的段的地址是此段的地址加上给定的偏移量;其大小由给定的参数指定。

      等效于以下代码:

      asSlice(offset, newSize, 1);
      
      参数:
      offset - 新段基本偏移量(相对于此段的地址),以字节为单位。
      newSize - 新段大小,以字节为单位。
      返回:
      此内存段的一个片段。
      抛出:
      IndexOutOfBoundsException - 如果offset < 0offset > byteSize()newSize < 0,或newSize > byteSize() - offset
      参见:
    • asSlice

      MemorySegmentPREVIEW asSlice(long offset, long newSize, long byteAlignment)
      返回此内存段的一个片段,位于给定偏移量处,并具有所提供的对齐约束。返回的段的地址是此段的地址加上给定的偏移量;其大小由给定的参数指定。
      参数:
      offset - 新段基本偏移量(相对于此段的地址),以字节为单位。
      newSize - 新段大小,以字节为单位。
      byteAlignment - 返回片段的对齐约束(以字节为单位)。
      返回:
      此内存段的一个片段。
      抛出:
      IndexOutOfBoundsException - 如果offset < 0offset > byteSize()newSize < 0,或newSize > byteSize() - offset
      IllegalArgumentException - 如果无法在提供的对齐约束下访问此段的offset
      IllegalArgumentException - 如果byteAlignment <= 0,或者如果byteAlignment不是2的幂。
    • asSlice

      default MemorySegmentPREVIEW asSlice(long offset, MemoryLayoutPREVIEW layout)
      返回此内存段的一个具有给定布局的片段,位于给定偏移量处。返回的段的地址是此段的地址加上给定的偏移量;其大小与提供的布局的大小相同。

      等效于以下代码:

      asSlice(offset, layout.byteSize(), layout.byteAlignment());
      
      参数:
      offset - 新段基本偏移量(相对于此段的地址),以字节为单位。
      layout - 段片段的布局。
      返回:
      此内存段的一个片段。
      抛出:
      IndexOutOfBoundsException - 如果offset < 0offset > byteSize(),或layout.byteSize() > byteSize() - offset
      IllegalArgumentException - 如果无法在由layout指定的对齐约束下访问此段的offset
      参见:
    • asSlice

      MemorySegmentPREVIEW asSlice(long offset)
      返回此内存段的一个片段,位于给定偏移量处。返回的段的地址是此段的地址加上给定的偏移量;其大小是通过从此段大小中减去指定偏移量来计算的。

      等效于以下代码:

      asSlice(offset, byteSize() - offset);
      
      参数:
      offset - 新段基本偏移量(相对于此段的地址),以字节为单位。
      返回:
      此内存段的一个片段。
      抛出:
      IndexOutOfBoundsException - 如果offset < 0,或offset > byteSize()
      参见:
    • reinterpret

      MemorySegmentPREVIEW reinterpret(long newSize)
      返回一个具有与此段相同地址和作用域的新内存段,但具有提供的大小。

      此方法是受限制的。受限制的方法是不安全的,如果使用不正确,可能会导致JVM崩溃,或者更糟糕的是,悄无声息地导致内存损坏。因此,客户端应避免依赖受限制的方法,并在可能的情况下使用安全和受支持的功能。

      参数:
      newSize - 返回段的大小。
      返回:
      一个新的内存段,具有与此段相同的地址和范围,但具有新提供的大小。
      抛出:
      IllegalArgumentException - 如果newSize < 0
      UnsupportedOperationException - 如果此段不是一个本机段。
      IllegalCallerException - 如果调用者在没有启用本机访问权限的模块中。
    • reinterpret

      返回一个新的内存段,具有与此段相同的地址和大小,但具有提供的范围。因此,在提供的区域关闭后,无法访问返回的段。此外,返回的段可以与提供的区域相关的限制一致地访问:也就是说,如果提供的区域是一个受限制的区域预览,则返回的段只能由区域的所有者线程访问,而不管与此段相关的限制。换句话说,此方法返回一个行为就像使用提供的区域分配的段。

      客户端可以指定一个可选的清理操作,当提供的范围无效时应执行该操作。此清理操作接收从此段获取的新内存段,如下所示:

      MemorySegment cleanupSegment = MemorySegment.ofAddress(this.address())
                                                  .reinterpret(byteSize());
      
      换句话说,清理操作接收一个与始终存活的新范围相关联的段,并且可以从任何线程访问。清理操作接受的段的大小为byteSize()

      此方法是受限制的。受限制的方法是不安全的,如果使用不正确,可能会导致JVM崩溃,或者更糟糕的是,悄悄导致内存损坏。因此,客户端应避免依赖受限制的方法,并在可能的情况下使用安全和受支持的功能。

      API注释:
      清理操作(如果存在)应注意不要泄漏接收到的段给可能在其支持的内存区域不再可用后访问段的外部客户端。此外,如果提供的范围是一个自动区域预览的范围,则清理操作不得阻止范围变得不可达。如果未能这样做,将永久阻止自动区域分配的内存区域被释放。
      参数:
      arena - 与返回段关联的区域。
      cleanup - 当提供的区域关闭时应执行的清理操作(可以为null)。
      返回:
      一个具有无限大小的新内存段。
      抛出:
      IllegalStateException - 如果arena.scope().isAlive() == false
      UnsupportedOperationException - 如果此段不是一个本机段。
      IllegalCallerException - 如果调用者在没有启用本机访问权限的模块中。
    • reinterpret

      MemorySegmentPREVIEW reinterpret(long newSize, ArenaPREVIEW arena, Consumer<MemorySegmentPREVIEW> cleanup)
      返回一个具有与此段相同地址的新段,但具有提供的大小和范围。因此,在提供的区域关闭后,无法访问返回的段。此外,如果返回的段可以与提供的区域相关的限制一致地访问:也就是说,如果提供的区域是一个受限制的区域预览,则返回的段只能由区域的所有者线程访问,而不管与此段相关的限制。换句话说,此方法返回一个行为就像使用提供的区域分配的段。

      客户端可以指定一个可选的清理操作,当提供的范围无效时应执行该操作。此清理操作接收从此段获取的新内存段,如下所示:

      MemorySegment cleanupSegment = MemorySegment.ofAddress(this.address())
                                                  .reinterpret(newSize);
      
      换句话说,清理操作接收一个与始终存活的新范围相关联的段,并且可以从任何线程访问。清理操作接受的段的大小为newSize

      此方法是受限制的。受限制的方法是不安全的,如果使用不正确,可能会导致JVM崩溃,或者更糟糕的是,悄悄导致内存损坏。因此,客户端应避免依赖受限制的方法,并在可能的情况下使用安全和受支持的功能。

      API注释:
      清理操作(如果存在)应注意不要泄漏接收到的段给可能在其支持的内存区域不再可用后访问段的外部客户端。此外,如果提供的范围是一个自动区域预览的范围,则清理操作不得阻止范围变得不可达。如果未能这样做,将永久阻止自动区域分配的内存区域被释放。
      参数:
      newSize - 返回段的大小。
      arena - 与返回段关联的区域。
      cleanup - 当提供的区域关闭时应执行的清理操作(可以为null)。
      返回:
      一个具有与此段相同地址的新段,但具有新大小,并且其范围设置为提供的区域的范围。
      抛出:
      UnsupportedOperationException - 如果此段不是一个本机段。
      IllegalArgumentException - 如果newSize < 0
      IllegalStateException - 如果arena.scope().isAlive() == false
      IllegalCallerException - 如果调用者在没有启用本机访问权限的模块中。
    • isReadOnly

      boolean isReadOnly()
      返回true,如果此段是只读的。
      返回:
      true,如果此段是只读的
      参见:
    • asReadOnly

      MemorySegmentPREVIEW asReadOnly()
      返回此段的只读视图。生成的段将与此段相同,但尝试覆盖返回段的内容将导致运行时异常。
      返回:
      一个此段的只读视图
      参见:
    • isNative

      boolean isNative()
      返回true,如果此段是一个本机段。本机段是通过Arena.allocate(long, long)预览(及相关)工厂创建的,或通过包装一个直接缓冲区创建的。
      返回:
      true,如果此段是本机段。
    • isMapped

      boolean isMapped()
      返回true,如果此段是一个映射段。映射内存段是通过FileChannel.map(FileChannel.MapMode, long, long, Arena)预览工厂创建的,或通过包装一个映射的字节缓冲区创建的。
      返回:
      true,如果此段是一个映射段。
    • asOverlappingSlice

      Optional<MemorySegmentPREVIEW> asOverlappingSlice(MemorySegmentPREVIEW other)
      返回此段的一个片段,即此段与提供的段之间的重叠部分。

      如果可以找到至少两个片段L1(来自S1)和L2(来自S2),这两个片段都由相同的内存区域支持,则两个段S1S2被认为是重叠的。因此,本机段不可能与堆段重叠;在这种情况下,或者当没有重叠发生时,将返回一个空的Optional

      参数:
      other - 用于与此段测试重叠的段。
      返回:
      此段的一个片段(发生重叠时)。
    • segmentOffset

      long segmentOffset(MemorySegmentPREVIEW other)
      返回所提供段的偏移量(以字节为单位),相对于此段。

      偏移量是相对于此段的地址的,并且可以是负值或正值。例如,如果两个段都是本机段,或者是由相同数组支持的堆段,则可以计算出结果偏移量如下:

      other.address() - address()
      
      如果段共享相同地址,则返回0。如果other是此段的一个切片,则偏移量始终为0 <= x < this.byteSize()
      参数:
      other - 要检索偏移量的段。
      返回:
      所提供段的相对偏移量(以字节为单位)。
      抛出:
      UnsupportedOperationException - 如果两个段无法比较,例如因为它们是不同类型,或者因为它们由不同的Java数组支持。
    • fill

      MemorySegmentPREVIEW fill(byte value)
      使用给定值填充此内存段的内容。

      更具体地说,给定值写入此段的每个地址。等效于(但可能比以下代码更有效):

      for (long offset = 0; offset < segment.byteSize(); offset++) {
          byteHandle.set(ValueLayout.JAVA_BYTE, offset, value);
      }
      
      但不考虑或保证设置特定内存元素的顺序。

      此方法可用于初始化或重置内存段的内容。

      参数:
      value - 要写入此段的值。
      返回:
      此内存段。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      UnsupportedOperationException - 如果此段是只读的
    • copyFrom

      default MemorySegmentPREVIEW copyFrom(MemorySegmentPREVIEW src)
      从给定源段执行批量复制到此段。更具体地说,将源段中偏移量0src.byteSize() - 1的字节复制到此段中偏移量0src.byteSize() - 1

      调用此方法等效于以下代码:

      MemorySegment.copy(src, 0, this, 0, src.byteSize());
      
      参数:
      src - 源段。
      返回:
      此段。
      抛出:
      IndexOutOfBoundsException - 如果src.byteSize() > this.byteSize()
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalStateException - 如果与src关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得src.isAccessibleBy(T) == false
      UnsupportedOperationException - 如果此段是只读的
    • mismatch

      default long mismatch(MemorySegmentPREVIEW other)
      查找并返回此段与给定其他段之间第一个不匹配的偏移量(以字节为单位)。偏移量是相对于每个段的地址,将在0(包括)到较小内存段的大小(以字节为单位)范围内。

      如果两个段共享一个公共前缀,则返回的偏移量是公共前缀的长度,因此在各自段内的该偏移量处存在两个段之间的不匹配。如果一个段是另一个段的正确前缀,则返回的偏移量是段大小中最小的,并且只对较大段有效。否则,没有不匹配,返回 -1

      参数:
      other - 要与此段进行不匹配测试的段。
      返回:
      第一个不匹配的相对偏移量(以字节为单位),否则如果没有不匹配则返回-1。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalStateException - 如果与other关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得other.isAccessibleBy(T) == false
    • isLoaded

      boolean isLoaded()
      确定此映射段的内容是否驻留在物理内存中。

      返回true意味着很可能此段中的所有数据都驻留在物理内存中,因此可以访问而不产生任何虚拟内存页错误或I/O操作。返回false并不一定意味着此段的内容未驻留在物理内存中。

      返回的值是一个提示,而不是保证,因为在调用此方法返回时,底层操作系统可能已经将此段的某些数据分页出去。

      返回:
      如果此段的内容很可能驻留在物理内存中,则返回true
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      UnsupportedOperationException - 如果此段不是映射内存段,例如如果isMapped() == false
    • load

      void load()
      将此映射段的内容加载到物理内存中。

      此方法尽最大努力确保在返回时,此段的内容驻留在物理内存中。调用此方法可能导致发生一些页面错误和I/O操作。

      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      UnsupportedOperationException - 如果此段不是映射内存段,例如如果isMapped() == false
    • unload

      void unload()
      从物理内存中卸载此映射段的内容。

      此方法尽最大努力确保此段的内容不再驻留在物理内存中。在调用此方法后访问此段的内容可能会导致一些页面错误和I/O操作(因为此段的内容可能需要重新分页)。

      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      UnsupportedOperationException - 如果此段不是映射内存段,例如如果isMapped() == false
    • force

      void force()
      强制将对此映射段内容所做的任何更改写入到由映射段文件描述符描述的存储设备中。

      如果与此映射段关联的文件描述符位于本地存储设备上,则当此方法返回时,保证自创建此段以来对此段所做的所有更改,或自上次调用此方法以来对此段所做的所有更改,都已写入该设备。

      如果与此映射段关联的文件描述符不位于本地设备上,则不提供此类保证。

      如果此段未以读/写模式映射(FileChannel.MapMode.READ_WRITE),则调用此方法可能没有效果。特别是,对于以只读或私有映射模式映射的段,该方法没有效果。对于特定于实现的映射模式,此方法可能有或可能没有效果。

      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      UnsupportedOperationException - 如果此段不是映射内存段,例如如果isMapped() == false
      UncheckedIOException - 如果将此段内容写入关联存储设备时发生I/O错误
    • asByteBuffer

      ByteBuffer asByteBuffer()
      将此段包装在ByteBuffer中。返回的缓冲区的某些属性与此段的属性相关联。具体来说,生成的缓冲区具有以下特征:

      返回的缓冲区的生命周期与此段的生命周期相关联。也就是说,在与此段关联的范围不再活动预览后访问返回的缓冲区将抛出一个IllegalStateException。类似地,如果从线程T访问返回的缓冲区,使得isAccessible(T) == false,将抛出一个WrongThreadException

      如果此段从单个线程可访问,在结果缓冲区上调用读/写I/O操作可能导致抛出未指定的异常。此类问题操作的示例包括AsynchronousSocketChannel.read(ByteBuffer)AsynchronousSocketChannel.write(ByteBuffer)

      最后,返回的缓冲区的字节顺序为ByteOrder.BIG_ENDIAN;可以使用ByteBuffer.order(java.nio.ByteOrder)更改此顺序。

      返回:
      此内存段的ByteBuffer视图。
      抛出:
      UnsupportedOperationException - 如果无法将此段映射到ByteBuffer实例,例如如果它是由除byte[]之外的数组支持的堆段,或者其大小大于Integer.MAX_VALUE
    • toArray

      byte[] toArray(ValueLayout.OfBytePREVIEW elementLayout)
      将此内存段的内容复制到一个新的字节数组中。
      参数:
      elementLayout - 源元素布局。如果与布局关联的字节顺序与本机顺序不同,则将在每个数组元素上执行字节交换操作。
      返回:
      从此内存段复制内容的新字节数组。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalStateException - 如果无法将此段的内容复制到byte[]实例中,例如其大小大于Integer.MAX_VALUE
    • toArray

      short[] toArray(ValueLayout.OfShortPREVIEW elementLayout)
      将此内存段的内容复制到一个新的短整型数组中。
      参数:
      elementLayout - 源元素布局。如果与布局关联的字节顺序与本机顺序不同,则将在每个数组元素上执行字节交换操作。
      返回:
      从此内存段复制内容的新短整型数组。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalStateException - 如果无法将此段的内容复制到short[]实例中,例如因为byteSize() % 2 != 0,或byteSize() / 2 > Integer.MAX_VALUE
    • toArray

      char[] toArray(ValueLayout.OfCharPREVIEW elementLayout)
      将此内存段的内容复制到一个新的字符数组中。
      参数:
      elementLayout - 源元素布局。如果与布局关联的字节顺序与本机顺序不同,则将在每个数组元素上执行字节交换操作。
      返回:
      从此内存段复制内容的新字符数组。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalStateException - 如果无法将此段的内容复制到char[]实例中,例如因为byteSize() % 2 != 0,或byteSize() / 2 > Integer.MAX_VALUE
    • toArray

      int[] toArray(ValueLayout.OfIntPREVIEW elementLayout)
      将此内存段的内容复制到一个新的整型数组中。
      参数:
      elementLayout - 源元素布局。如果与布局关联的字节顺序与本机顺序不同,则将在每个数组元素上执行字节交换操作。
      返回:
      从此内存段复制内容的新整型数组。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalStateException - 如果无法将此段的内容复制到int[]实例中,例如因为byteSize() % 4 != 0,或byteSize() / 4 > Integer.MAX_VALUE
    • toArray

      float[] toArray(ValueLayout.OfFloatPREVIEW elementLayout)
      将此内存段的内容复制到一个新的浮点数数组中。
      参数:
      elementLayout - 源元素布局。如果与布局关联的字节顺序与本机顺序不同,则将对每个数组元素执行字节交换操作。
      返回:
      一个新的浮点数数组,其内容从此内存段复制而来。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalStateException - 如果此段的内容无法复制到float[]实例中,例如因为byteSize() % 4 != 0,或byteSize() / 4 > Integer.MAX_VALUE
    • toArray

      long[] toArray(ValueLayout.OfLongPREVIEW elementLayout)
      将此内存段的内容复制到一个新的长整型数组中。
      参数:
      elementLayout - 源元素布局。如果与布局关联的字节顺序与本机顺序不同,则将对每个数组元素执行字节交换操作。
      返回:
      一个新的长整型数组,其内容从此内存段复制而来。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalStateException - 如果此段的内容无法复制到long[]实例中,例如因为byteSize() % 8 != 0,或byteSize() / 8 > Integer.MAX_VALUE
    • toArray

      double[] toArray(ValueLayout.OfDoublePREVIEW elementLayout)
      将此内存段的内容复制到一个新的双精度浮点数数组中。
      参数:
      elementLayout - 源元素布局。如果与布局关联的字节顺序与本机顺序不同,则将对每个数组元素执行字节交换操作。
      返回:
      一个新的双精度浮点数数组,其内容从此内存段复制而来。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalStateException - 如果此段的内容无法复制到double[]实例中,例如因为byteSize() % 8 != 0,或byteSize() / 8 > Integer.MAX_VALUE
    • getUtf8String

      default String getUtf8String(long offset)
      从给定偏移量处的此段中读取一个以UTF-8编码的以空字符结尾的字符串。

      此方法始终使用此字符集的默认替换字符串替换格式错误的输入和无法映射的字符序列。当需要对解码过程进行更多控制时,应使用CharsetDecoder类。

      参数:
      offset - 字节偏移量(相对于此段地址),在此处将进行访问操作。
      返回:
      从给定起始地址读取的字节构造的Java字符串,直到(但不包括)第一个'\0'终止字符(假设找到一个)。
      抛出:
      IllegalArgumentException - 如果UTF-8字符串的大小大于平台支持的最大字符串。
      IndexOutOfBoundsException - 如果offset < 0offset > byteSize() - S,其中S是UTF-8字符串的大小(包括终止字符)。
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
    • setUtf8String

      default void setUtf8String(long offset, String str)
      将给定的字符串写入此段中的给定偏移量处,使用UTF-8编码将其转换为以空字符结尾的字节序列。

      此方法始终使用此字符集的默认替换字符串替换格式错误的输入和无法映射的字符序列。当需要对解码过程进行更多控制时,应使用CharsetDecoder类。

      如果给定的字符串包含任何'\0'字符,它们也将被复制。这意味着,根据用于读取字符串的方法,例如getUtf8String(long),再次读取时字符串将显示为被截断。

      参数:
      offset - 字节偏移量(相对于此段地址),在此处将进行访问操作。此写操作的最终地址可以表示为address() + offset
      str - 要写入此段的Java字符串。
      抛出:
      IndexOutOfBoundsException - 如果offset < 0offset > byteSize() - str.getBytes().length() + 1
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
    • ofBuffer

      static MemorySegmentPREVIEW ofBuffer(Buffer buffer)
      创建一个由与给定Buffer实例相同的内存区域支持的内存段。该段从缓冲区的位置(包括)开始,到缓冲区的限制(不包括)结束。

      如果缓冲区是只读的,则生成的段也是只读的。此外,如果缓冲区是直接缓冲区,返回的段是本机段;否则返回的内存段是堆段。

      如果提供的缓冲区是通过在其asByteBuffer()上调用的内存段获得的,其范围预览S,返回的段将与相同范围S关联。否则,返回段的范围是始终活动的新范围。

      与返回段关联的范围使提供的缓冲区可访问。因此,如果提供的缓冲区是直接缓冲区,则只要保持返回段(或其任何切片)可访问,其支持的内存区域就不会被释放。

      参数:
      buffer - 要转换为新内存段的缓冲区实例。
      返回:
      从给定缓冲区实例派生的内存段。
      抛出:
      IllegalArgumentException - 如果提供的buffer是堆缓冲区,但不是由数组支持的。例如,通过(CharBuffer.wrap(CharSequence)CharBuffer.wrap(char[], int, int))直接或间接获得的缓冲区不由数组支持。
    • ofArray

      static MemorySegmentPREVIEW ofArray(byte[] byteArray)
      创建一个由持有给定字节数组的堆内存区域支持的堆段。返回段的范围是始终活动的新范围,并使给定数组可访问。返回段始终可以从任何线程访问。其address()设置为零。
      参数:
      byteArray - 支持堆内存段的原始数组。
      返回:
      由字节数组支持的堆内存段。
    • ofArray

      static MemorySegmentPREVIEW ofArray(char[] charArray)
      创建一个由持有给定字符数组的堆内存区域支持的堆段。返回段的范围是始终活动的新范围,并使给定数组可访问。返回段始终可以从任何线程访问。其address()设置为零。
      参数:
      charArray - 支持堆段的原始数组。
      返回:
      由字符数组支持的堆内存段。
    • ofArray

      static MemorySegmentPREVIEW ofArray(short[] shortArray)
      创建一个由持有给定短整型数组的堆内存区域支持的堆段。返回段的范围是始终活动的新范围,并使给定数组可访问。返回段始终可以从任何线程访问。其address()设置为零。
      参数:
      shortArray - 支持堆段的原始数组。
      返回:
      由short数组支持的堆内存段。
    • ofArray

      static MemorySegmentPREVIEW ofArray(int[] intArray)
      创建一个由给定int数组的堆段支持的堆段。返回的段的范围是一个始终存活的新范围,并保持给定数组可访问。返回的段始终可以从任何线程访问。其address()设置为零。
      参数:
      intArray - 支持堆段的原始数组。
      返回:
      由int数组支持的堆内存段。
    • ofArray

      static MemorySegmentPREVIEW ofArray(float[] floatArray)
      创建一个由给定float数组的堆段支持的堆段。返回的段的范围是一个始终存活的新范围,并保持给定数组可访问。返回的段始终可以从任何线程访问。其address()设置为零。
      参数:
      floatArray - 支持堆段的原始数组。
      返回:
      由float数组支持的堆内存段。
    • ofArray

      static MemorySegmentPREVIEW ofArray(long[] longArray)
      创建一个由给定long数组的堆段支持的堆段。返回的段的范围是一个始终存活的新范围,并保持给定数组可访问。返回的段始终可以从任何线程访问。其address()设置为零。
      参数:
      longArray - 支持堆段的原始数组。
      返回:
      由long数组支持的堆内存段。
    • ofArray

      static MemorySegmentPREVIEW ofArray(double[] doubleArray)
      创建一个由给定double数组的堆段支持的堆段。返回的段的范围是一个始终存活的新范围,并保持给定数组可访问。返回的段始终可以从任何线程访问。其address()设置为零。
      参数:
      doubleArray - 支持堆段的原始数组。
      返回:
      由double数组支持的堆内存段。
    • ofAddress

      static MemorySegmentPREVIEW ofAddress(long address)
      从给定的地址值创建一个零长度的本机段。返回的段与始终存活的范围关联,并且可以从任何线程访问。

      在32位平台上,给定的地址值将被规范化,使得返回的内存段的最高位(“最左侧”)32位的address设置为零。

      参数:
      address - 返回的本机段的地址。
      返回:
      具有给定地址的零长度本机段。
    • copy

      static void copy(MemorySegmentPREVIEW srcSegment, long srcOffset, MemorySegmentPREVIEW dstSegment, long dstOffset, long bytes)
      从源段批量复制到目标段。更具体地说,源段中偏移量srcOffsetsrcOffset + bytes - 1处的字节将被复制到目标段中偏移量dstOffsetdstOffset + bytes - 1处。

      如果源段与目标段重叠,则复制将被执行,就好像首先将源段中偏移量srcOffsetsrcOffset + bytes - 1处的字节复制到具有大小bytes的临时段中,然后将临时段的内容复制到目标段中偏移量dstOffsetdstOffset + bytes - 1处。

      如果在罕见情况下,源段和目标段不重叠,但使用不同地址引用相同后备存储的重叠区域,则批量复制的结果是未指定的。例如,如果将同一文件映射到两个段中,则可能会发生这种情况。

      调用此方法等效于以下代码:

      MemorySegment.copy(srcSegment, ValueLayout.JAVA_BYTE, srcOffset, dstSegment, ValueLayout.JAVA_BYTE, dstOffset, bytes);
      
      参数:
      srcSegment - 源段。
      srcOffset - 源段的起始偏移量(以字节为单位)。
      dstSegment - 目标段。
      dstOffset - 目标段的起始偏移量(以字节为单位)。
      bytes - 要复制的字节数。
      抛出:
      IllegalStateException - 如果与srcSegment关联的范围不是存活的预览
      WrongThreadException - 如果从线程T调用此方法,使得srcSegment.isAccessibleBy(T) == false
      IllegalStateException - 如果与dstSegment关联的范围不是存活的预览
      WrongThreadException - 如果从线程T调用此方法,使得dstSegment.isAccessibleBy(T) == false
      IndexOutOfBoundsException - 如果srcOffset > srcSegment.byteSize() - bytes或者dstOffset > dstSegment.byteSize() - bytes,或者srcOffsetdstOffsetbytes中任何一个< 0
      UnsupportedOperationException - 如果dstSegment只读的
    • copy

      static void copy(MemorySegmentPREVIEW srcSegment, ValueLayoutPREVIEW srcElementLayout, long srcOffset, MemorySegmentPREVIEW dstSegment, ValueLayoutPREVIEW dstElementLayout, long dstOffset, long elementCount)
      从源段批量复制到目标段。更具体地说,如果S是元素布局的字节大小,源段中偏移量srcOffsetsrcOffset + (elementCount * S) - 1处的字节将被复制到目标段中偏移量dstOffsetdstOffset + (elementCount * S) - 1处。

      复制以元素方式进行:源段中的字节被解释为元素序列,其布局为srcElementLayout,而目标段中的字节被解释为元素序列,其布局为dstElementLayout。两个元素布局必须具有相同的大小S。如果两个元素布局的字节顺序不同,则在复制操作期间相应地交换要复制的每个元素的字节。

      如果源段与目标段重叠,则复制将被执行,就好像首先将源段中偏移量srcOffsetsrcOffset + (elementCount * S) - 1处的字节复制到具有大小bytes的临时段中,然后将临时段的内容复制到目标段中偏移量dstOffsetdstOffset + (elementCount * S) - 1处。

      如果在罕见情况下,源段和目标段不重叠,但使用不同地址引用相同后备存储的重叠区域,则批量复制的结果是未指定的。例如,如果将同一文件映射到两个段中,则可能会发生这种情况。

      参数:
      srcSegment - 源段。
      srcElementLayout - 与源段关联的元素布局。
      srcOffset - 源段的起始偏移量(以字节为单位)。
      dstSegment - 目标段。
      dstElementLayout - 与目标段关联的元素布局。
      dstOffset - 目标段的起始偏移量(以字节为单位)。
      elementCount - 要复制的元素数量。
      抛出:
      IllegalArgumentException - 如果元素布局大小不同,如果源(或目标)段/偏移与源(或目标)元素布局中的对齐约束不兼容,或者如果源(或目标)元素布局的对齐大于其大小。
      IllegalStateException - 如果与srcSegment关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得srcSegment().isAccessibleBy(T) == false
      IllegalStateException - 如果与dstSegment关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得dstSegment().isAccessibleBy(T) == false
      UnsupportedOperationException - 如果dstSegment只读的
      IndexOutOfBoundsException - 如果elementCount * srcLayout.byteSize()elementCount * dtsLayout.byteSize()溢出。
      IndexOutOfBoundsException - 如果dstOffset > dstSegment.byteSize() - (elementCount * dstLayout.byteSize())
      IndexOutOfBoundsException - 如果srcOffsetdstOffsetelementCount中有任何一个< 0
    • get

      default byte get(ValueLayout.OfBytePREVIEW layout, long offset)
      从给定偏移量处读取此段中的一个字节,使用给定的布局。
      参数:
      layout - 要读取的内存区域的布局。
      offset - 将发生此访问操作的字节偏移量(相对于此段地址)。
      返回:
      从此段中读取的一个字节值。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容
      IndexOutOfBoundsException - 如果offset > byteSize() - layout.byteSize()
    • set

      default void set(ValueLayout.OfBytePREVIEW layout, long offset, byte value)
      在给定偏移量处,使用给定的布局将一个字节写入此段中。
      参数:
      layout - 要写入的内存区域的布局。
      offset - 将发生此访问操作的字节偏移量(相对于此段地址)。
      value - 要写入的字节值。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容
      IndexOutOfBoundsException - 如果offset > byteSize() - layout.byteSize()
      UnsupportedOperationException - 如果此段是只读的
    • get

      default boolean get(ValueLayout.OfBooleanPREVIEW layout, long offset)
      从给定偏移量处读取此段中的一个布尔值,使用给定的布局。
      参数:
      layout - 要读取的内存区域的布局。
      offset - 将发生此访问操作的字节偏移量(相对于此段地址)。
      返回:
      从此段中读取的一个布尔值。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容
      IndexOutOfBoundsException - 如果offset > byteSize() - layout.byteSize()
    • set

      default void set(ValueLayout.OfBooleanPREVIEW layout, long offset, boolean value)
      在给定偏移量处,使用给定的布局将一个布尔值写入此段中。
      参数:
      layout - 要写入的内存区域的布局。
      offset - 将发生此访问操作的字节偏移量(相对于此段地址)。
      value - 要写入的布尔值。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容
      IndexOutOfBoundsException - 如果offset > byteSize() - layout.byteSize()
      UnsupportedOperationException - 如果此段是只读的
    • get

      default char get(ValueLayout.OfCharPREVIEW layout, long offset)
      从给定偏移量处读取此段中的一个字符,使用给定的布局。
      参数:
      layout - 要读取的内存区域的布局。
      offset - 将发生此访问操作的字节偏移量(相对于此段地址)。
      返回:
      从此段中读取的一个字符值。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容
      IndexOutOfBoundsException - 如果offset > byteSize() - layout.byteSize()
    • set

      default void set(ValueLayout.OfCharPREVIEW layout, long offset, char value)
      在给定偏移量处,使用给定的布局将一个字符写入此段中。
      参数:
      layout - 要写入的内存区域的布局。
      offset - 以字节为单位的偏移量(相对于此段地址),在此访问操作将发生。
      value - 要写入的char值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容
      IndexOutOfBoundsException - 如果offset > byteSize() - layout.byteSize()
      UnsupportedOperationException - 如果此段是只读的
    • get

      default short get(ValueLayout.OfShortPREVIEW layout, long offset)
      从给定偏移量处的此段中读取一个short,使用给定的布局。
      参数:
      layout - 要读取的内存区域的布局。
      offset - 以字节为单位的偏移量(相对于此段地址),在此访问操作将发生。
      返回:
      从此段中读取的short值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容
      IndexOutOfBoundsException - 如果offset > byteSize() - layout.byteSize()
    • set

      default void set(ValueLayout.OfShortPREVIEW layout, long offset, short value)
      在给定偏移量处的此段中写入一个short,使用给定的布局。
      参数:
      layout - 要写入的内存区域的布局。
      offset - 以字节为单位的偏移量(相对于此段地址),在此访问操作将发生。
      value - 要写入的short值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容
      IndexOutOfBoundsException - 如果offset > byteSize() - layout.byteSize()
      UnsupportedOperationException - 如果此段是只读的
    • get

      default int get(ValueLayout.OfIntPREVIEW layout, long offset)
      从给定偏移量处的此段中读取一个int,使用给定的布局。
      参数:
      layout - 要读取的内存区域的布局。
      offset - 以字节为单位的偏移量(相对于此段地址),在此访问操作将发生。
      返回:
      从此段中读取的int值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容
      IndexOutOfBoundsException - 如果offset > byteSize() - layout.byteSize()
    • set

      default void set(ValueLayout.OfIntPREVIEW layout, long offset, int value)
      在给定偏移量处的此段中写入一个int,使用给定的布局。
      参数:
      layout - 要写入的内存区域的布局。
      offset - 以字节为单位的偏移量(相对于此段地址),在此访问操作将发生。
      value - 要写入的int值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容
      IndexOutOfBoundsException - 如果offset > byteSize() - layout.byteSize()
      UnsupportedOperationException - 如果此段是只读的
    • get

      default float get(ValueLayout.OfFloatPREVIEW layout, long offset)
      从给定偏移量处的此段中读取一个float,使用给定的布局。
      参数:
      layout - 要读取的内存区域的布局。
      offset - 以字节为单位的偏移量(相对于此段地址),在此访问操作将发生。
      返回:
      从此段中读取的float值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容
      IndexOutOfBoundsException - 如果offset > byteSize() - layout.byteSize()
    • set

      default void set(ValueLayout.OfFloatPREVIEW layout, long offset, float value)
      在给定偏移量处的此段中写入一个float,使用给定的布局。
      参数:
      layout - 要写入的内存区域的布局。
      offset - 以字节为单位的偏移量(相对于此段地址),在此访问操作将发生。
      value - 要写入的float值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容
      IndexOutOfBoundsException - 如果offset > byteSize() - layout.byteSize()
      UnsupportedOperationException - 如果此段是只读的
    • get

      default long get(ValueLayout.OfLongPREVIEW layout, long offset)
      从给定偏移量处的此段中读取一个long,使用给定的布局。
      参数:
      layout - 要读取的内存区域的布局。
      offset - 以字节为单位的偏移量(相对于此段地址),在此访问操作将发生。
      返回:
      从此段中读取的长整型值。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容
      IndexOutOfBoundsException - 如果offset > byteSize() - layout.byteSize()
    • set

      default void set(ValueLayout.OfLongPREVIEW layout, long offset, long value)
      在给定的偏移量处,使用给定的布局将长整型写入此段。
      参数:
      layout - 要写入的内存区域的布局。
      offset - 以字节为单位的偏移量(相对于此段地址),在此访问操作将发生。
      value - 要写入的长整型值。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容
      IndexOutOfBoundsException - 如果offset > byteSize() - layout.byteSize()
      UnsupportedOperationException - 如果此段是只读的
    • get

      default double get(ValueLayout.OfDoublePREVIEW layout, long offset)
      在给定的偏移量处,使用给定的布局从此段中读取双精度值。
      参数:
      layout - 要读取的内存区域的布局。
      offset - 以字节为单位的偏移量(相对于此段地址),在此访问操作将发生。
      返回:
      从此段中读取的双精度值。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容
      IndexOutOfBoundsException - 如果offset > byteSize() - layout.byteSize()
    • set

      default void set(ValueLayout.OfDoublePREVIEW layout, long offset, double value)
      在给定的偏移量处,使用给定的布局将双精度值写入此段。
      参数:
      layout - 要写入的内存区域的布局。
      offset - 以字节为单位的偏移量(相对于此段地址),在此访问操作将发生。
      value - 要写入的双精度值。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容
      IndexOutOfBoundsException - 如果offset > byteSize() - layout.byteSize()
      UnsupportedOperationException - 如果此段是只读的
    • get

      default MemorySegmentPREVIEW get(AddressLayoutPREVIEW layout, long offset)
      在给定的偏移量处,使用给定的布局从此段中读取地址。读取的地址被包装在一个本机段中,关联一个始终处于活动状态的新范围。在正常情况下,返回段的大小为0。但是,如果提供的地址布局具有目标布局预览T,则返回段的大小设置为T.byteSize()
      参数:
      layout - 要读取的内存区域的布局。
      offset - 以字节为单位的偏移量(相对于此段地址),在此访问操作将发生。
      返回:
      包装从此段中读取的地址的本机段。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容
      IllegalArgumentException - 如果提供的地址布局具有目标布局预览T,并且返回段的地址T中的对齐约束不兼容
      IndexOutOfBoundsException - 如果offset > byteSize() - layout.byteSize()
    • set

      default void set(AddressLayoutPREVIEW layout, long offset, MemorySegmentPREVIEW value)
      在给定的偏移量处,使用给定的布局将地址写入此段。
      参数:
      layout - 要写入的内存区域的布局。
      offset - 以字节为单位的偏移量(相对于此段地址),在此访问操作将发生。
      value - 要写入的地址值。
      抛出:
      IllegalStateException - 如果与此段关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容
      IndexOutOfBoundsException - 如果offset > byteSize() - layout.byteSize()
      UnsupportedOperationException - 如果此段是只读的
      UnsupportedOperationException - 如果value不是本机的段。
    • getAtIndex

      default byte getAtIndex(ValueLayout.OfBytePREVIEW layout, long index)
      在给定的索引处,按给定的布局大小进行缩放,从此段中读取一个字节。
      参数:
      layout - 要读取的内存区域的布局。
      index - 逻辑索引。可以将访问操作发生的偏移量(相对于此段地址)表示为(index * layout.byteSize())
      返回:
      从此段中读取的字节值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容,或者布局对齐大于其大小。
      IndexOutOfBoundsException - 如果index * byteSize()溢出。
      IndexOutOfBoundsException - 如果index * byteSize() > byteSize() - layout.byteSize()
    • getAtIndex

      default boolean getAtIndex(ValueLayout.OfBooleanPREVIEW layout, long index)
      从给定索引处的此段中读取一个布尔值,按给定布局大小缩放。
      参数:
      layout - 要读取的内存区域的布局。
      index - 逻辑索引。可以将访问操作发生的偏移量(相对于此段地址)表示为(index * layout.byteSize())
      返回:
      从此段中读取的布尔值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容,或者布局对齐大于其大小。
      IndexOutOfBoundsException - 如果index * byteSize()溢出。
      IndexOutOfBoundsException - 如果index * byteSize() > byteSize() - layout.byteSize()
    • getAtIndex

      default char getAtIndex(ValueLayout.OfCharPREVIEW layout, long index)
      从给定索引处的此段中读取一个字符,按给定布局大小缩放。
      参数:
      layout - 要读取的内存区域的布局。
      index - 逻辑索引。可以将访问操作发生的偏移量(相对于此段地址)表示为(index * layout.byteSize())
      返回:
      从此段中读取的字符值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容,或者布局对齐大于其大小。
      IndexOutOfBoundsException - 如果index * byteSize()溢出。
      IndexOutOfBoundsException - 如果index * byteSize() > byteSize() - layout.byteSize()
    • setAtIndex

      default void setAtIndex(ValueLayout.OfCharPREVIEW layout, long index, char value)
      在给定索引处的此段中写入一个字符,按给定布局大小缩放。
      参数:
      layout - 要写入的内存区域的布局。
      index - 逻辑索引。可以将访问操作发生的偏移量(相对于此段地址)表示为(index * layout.byteSize())
      value - 要写入的字符值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容,或者布局对齐大于其大小。
      IndexOutOfBoundsException - 如果index * byteSize()溢出。
      IndexOutOfBoundsException - 如果index * byteSize() > byteSize() - layout.byteSize()
      UnsupportedOperationException - 如果此段是只读的
    • getAtIndex

      default short getAtIndex(ValueLayout.OfShortPREVIEW layout, long index)
      从给定索引处的此段中读取一个短整数,按给定布局大小缩放。
      参数:
      layout - 要读取的内存区域的布局。
      index - 逻辑索引。可以将访问操作发生的偏移量(相对于此段地址)表示为(index * layout.byteSize())
      返回:
      从此段中读取的短整数值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容,或者布局对齐大于其大小。
      IndexOutOfBoundsException - 如果index * byteSize()溢出。
      IndexOutOfBoundsException - 如果index * byteSize() > byteSize() - layout.byteSize()
    • setAtIndex

      default void setAtIndex(ValueLayout.OfBytePREVIEW layout, long index, byte value)
      在给定索引处的此段中写入一个字节,按给定布局大小缩放。
      参数:
      layout - 要写入的内存区域的布局。
      index - 逻辑索引。可以将访问操作发生的偏移量(相对于此段地址)表示为(index * layout.byteSize())
      value - 要写入的短整数值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容,或者布局对齐大于其大小。
      IndexOutOfBoundsException - 如果index * byteSize()溢出。
      IndexOutOfBoundsException - 如果index * byteSize() > byteSize() - layout.byteSize()
      UnsupportedOperationException - 如果此段是只读的
    • setAtIndex

      default void setAtIndex(ValueLayout.OfBooleanPREVIEW layout, long index, boolean value)
      在给定索引处的此段中写入一个布尔值,按给定布局大小缩放。
      参数:
      layout - 要写入的内存区域的布局。
      index - 逻辑索引。访问操作将发生的偏移量(相对于此段地址)可以表示为(index * layout.byteSize())
      value - 要写入的short值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容,或者布局对齐大于其大小。
      IndexOutOfBoundsException - 如果index * byteSize()溢出。
      IndexOutOfBoundsException - 如果index * byteSize() > byteSize() - layout.byteSize()
      UnsupportedOperationException - 如果此段是只读的
    • setAtIndex

      default void setAtIndex(ValueLayout.OfShortPREVIEW layout, long index, short value)
      在给定索引处,按给定布局大小缩放,将short写入此段。
      参数:
      layout - 要写入的内存区域的布局。
      index - 逻辑索引。访问操作将发生的偏移量(相对于此段地址)可以表示为(index * layout.byteSize())
      value - 要写入的short值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容,或者布局对齐大于其大小。
      IndexOutOfBoundsException - 如果index * byteSize()溢出。
      IndexOutOfBoundsException - 如果index * byteSize() > byteSize() - layout.byteSize()
      UnsupportedOperationException - 如果此段是只读的
    • getAtIndex

      default int getAtIndex(ValueLayout.OfIntPREVIEW layout, long index)
      按给定布局大小缩放,在给定索引处从此段读取int。
      参数:
      layout - 要读取的内存区域的布局。
      index - 逻辑索引。访问操作将发生的偏移量(相对于此段地址)可以表示为(index * layout.byteSize())
      返回:
      从此段读取的int值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容,或者布局对齐大于其大小。
      IndexOutOfBoundsException - 如果index * byteSize()溢出。
      IndexOutOfBoundsException - 如果index * byteSize() > byteSize() - layout.byteSize()
    • setAtIndex

      default void setAtIndex(ValueLayout.OfIntPREVIEW layout, long index, int value)
      按给定布局大小缩放,在给定索引处将int写入此段。
      参数:
      layout - 要写入的内存区域的布局。
      index - 逻辑索引。访问操作将发生的偏移量(相对于此段地址)可以表示为(index * layout.byteSize())
      value - 要写入的int值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容,或者布局对齐大于其大小。
      IndexOutOfBoundsException - 如果index * byteSize()溢出。
      IndexOutOfBoundsException - 如果index * byteSize() > byteSize() - layout.byteSize()
      UnsupportedOperationException - 如果此段是只读的
    • getAtIndex

      default float getAtIndex(ValueLayout.OfFloatPREVIEW layout, long index)
      按给定布局大小缩放,在给定索引处从此段读取float。
      参数:
      layout - 要读取的内存区域的布局。
      index - 逻辑索引。访问操作将发生的偏移量(相对于此段地址)可以表示为(index * layout.byteSize())
      返回:
      从此段读取的float值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容,或者布局对齐大于其大小。
      IndexOutOfBoundsException - 如果index * byteSize()溢出。
      IndexOutOfBoundsException - 如果index * byteSize() > byteSize() - layout.byteSize()
    • setAtIndex

      default void setAtIndex(ValueLayout.OfFloatPREVIEW layout, long index, float value)
      按给定布局大小缩放,在给定索引处将float写入此段。
      参数:
      layout - 要写入的内存区域的布局。
      index - 逻辑索引。访问操作将发生的偏移量(相对于此段地址)可以表示为(index * layout.byteSize())
      value - 要写入的float值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容,或者布局对齐大于其大小。
      IndexOutOfBoundsException - 如果index * byteSize()溢出。
      IndexOutOfBoundsException - 如果index * byteSize() > byteSize() - layout.byteSize()
      UnsupportedOperationException - 如果此段是只读的
    • getAtIndex

      default long getAtIndex(ValueLayout.OfLongPREVIEW layout, long index)
      按给定布局大小缩放,在给定索引处从此段读取long。
      参数:
      layout - 要读取的内存区域的布局。
      index - 逻辑索引。可以将访问操作发生的偏移量(相对于此段地址)表示为(index * layout.byteSize())
      返回:
      从此段读取的长整型值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容,或者布局对齐大于其大小。
      IndexOutOfBoundsException - 如果index * byteSize()溢出。
      IndexOutOfBoundsException - 如果index * byteSize() > byteSize() - layout.byteSize()
    • setAtIndex

      default void setAtIndex(ValueLayout.OfLongPREVIEW layout, long index, long value)
      在给定索引处,按给定布局大小缩放将长整型写入此段。
      参数:
      layout - 要写入的内存区域的布局。
      index - 逻辑索引。可以将访问操作发生的偏移量(相对于此段地址)表示为(index * layout.byteSize())
      value - 要写入的长整型值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容,或者布局对齐大于其大小。
      IndexOutOfBoundsException - 如果index * byteSize()溢出。
      IndexOutOfBoundsException - 如果index * byteSize() > byteSize() - layout.byteSize()
      UnsupportedOperationException - 如果此段是只读的
    • getAtIndex

      default double getAtIndex(ValueLayout.OfDoublePREVIEW layout, long index)
      在给定索引处,按给定布局大小缩放从此段读取双精度数。
      参数:
      layout - 要读取的内存区域的布局。
      index - 逻辑索引。可以将访问操作发生的偏移量(相对于此段地址)表示为(index * layout.byteSize())
      返回:
      从此段读取的双精度数值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容,或者布局对齐大于其大小。
      IndexOutOfBoundsException - 如果index * byteSize()溢出。
      IndexOutOfBoundsException - 如果index * byteSize() > byteSize() - layout.byteSize()
    • setAtIndex

      default void setAtIndex(ValueLayout.OfDoublePREVIEW layout, long index, double value)
      在给定索引处,按给定布局大小缩放将双精度数值写入此段。
      参数:
      layout - 要写入的内存区域的布局。
      index - 逻辑索引。可以将访问操作发生的偏移量(相对于此段地址)表示为(index * layout.byteSize())
      value - 要写入的双精度数值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容,或者布局对齐大于其大小。
      IndexOutOfBoundsException - 如果index * byteSize()溢出。
      IndexOutOfBoundsException - 如果index * byteSize() > byteSize() - layout.byteSize()
      UnsupportedOperationException - 如果此段是只读的
    • getAtIndex

      default MemorySegmentPREVIEW getAtIndex(AddressLayoutPREVIEW layout, long index)
      在给定索引处,按给定布局大小缩放从此段读取地址。读取的地址包装在一个本机段中,关联一个始终处于活动状态的新scope。在正常情况下,返回段的大小为0。但是,如果提供的地址布局具有目标布局预览T,则返回段的大小设置为T.byteSize()
      参数:
      layout - 要读取的内存区域的布局。
      index - 逻辑索引。可以将访问操作发生的偏移量(相对于此段地址)表示为(index * layout.byteSize())
      返回:
      从此段读取的地址包装在一个本机段中。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容,或者布局对齐大于其大小。
      IllegalArgumentException - 如果提供的地址布局具有目标布局预览T,并且返回段的地址T中的对齐约束不兼容
      IndexOutOfBoundsException - 如果index * byteSize()溢出。
      IndexOutOfBoundsException - 如果index * byteSize() > byteSize() - layout.byteSize()
    • setAtIndex

      default void setAtIndex(AddressLayoutPREVIEW layout, long index, MemorySegmentPREVIEW value)
      在给定索引处,按给定布局大小缩放将地址写入此段。
      参数:
      layout - 要写入的内存区域的布局。
      index - 逻辑索引。可以将访问操作发生的偏移量(相对于此段地址)表示为(index * layout.byteSize())
      value - 要写入的地址值。
      抛出:
      IllegalStateException - 如果与此段关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得isAccessibleBy(T) == false
      IllegalArgumentException - 如果访问操作与提供的布局中的对齐约束不兼容,或者布局对齐大于其大小。
      IndexOutOfBoundsException - 如果index * byteSize()溢出。
      IndexOutOfBoundsException - 如果index * byteSize() > byteSize() - layout.byteSize()
      UnsupportedOperationException - 如果此段是只读的
      UnsupportedOperationException - 如果value不是本机段。
    • equals

      boolean equals(Object that)
      将指定的对象与此内存段进行比较以确定是否相等。仅当指定的对象也是内存段,并且两个段引用内存中某个区域的相同位置时,才返回true。更具体地,要使两个段s1s2被视为相等,必须满足以下所有条件:
      • s1.heapBase().equals(s2.heapBase()),即,两个段必须是相同类型;两者都是本机段,由堆外存储支持,或者两者由相同的堆Java对象支持;
      • s1.address() == s2.address(),即,两个段的地址应该相同。这意味着两个段要么引用某个堆外区域中的相同位置,要么它们引用其关联的Java对象内部的相同偏移量。
      覆盖:
      equals 在类 Object
      API注释:
      此方法不执行两个内存段内容的结构比较。客户端可以使用mismatch(MemorySegment)方法来结构化比较内存段。请注意,此方法不比较两个段的时间和空间边界。因此,它适用于检查两个段是否具有相同的地址。
      参数:
      that - 要与此内存段进行相等比较的对象。
      返回:
      如果指定的对象等于此内存段,则返回true
      参见:
    • hashCode

      int hashCode()
      返回此内存段的哈希码值。
      覆盖:
      hashCode 在类 Object
      返回:
      此内存段的哈希码值
      参见:
    • copy

      static void copy(MemorySegmentPREVIEW srcSegment, ValueLayoutPREVIEW srcLayout, long srcOffset, Object dstArray, int dstIndex, int elementCount)
      从源内存段复制一定数量的元素到目标数组。这些元素的大小和对齐约束由给定的布局指定,从源段开始读取,从给定偏移量(以字节表示)开始,复制到目标数组的给定索引处。支持的数组类型包括byte[]char[]short[]int[]float[]long[]double[]
      参数:
      srcSegment - 源段。
      srcLayout - 源元素布局。如果与布局关联的字节顺序与本机顺序不同,则将在每个数组元素上执行字节交换操作。
      srcOffset - 源段的起始偏移量,以字节为单位。
      dstArray - 目标数组。
      dstIndex - 目标数组的起始索引。
      elementCount - 要复制的数组元素数量。
      抛出:
      IllegalStateException - 如果与srcSegment关联的scope不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得srcSegment().isAccessibleBy(T) == false
      IllegalArgumentException - 如果dstArray不是数组,或者如果它是数组但其类型不受支持。
      IllegalArgumentException - 如果目标数组组件类型与srcLayout.carrier()不匹配。
      IllegalArgumentException - 如果offset与源元素布局中的对齐约束不兼容
      IllegalArgumentException - 如果srcLayout.byteAlignment() > srcLayout.byteSize()
      IndexOutOfBoundsException - 如果elementCount * srcLayout.byteSize()溢出。
      IndexOutOfBoundsException - 如果srcOffset > srcSegment.byteSize() - (elementCount * srcLayout.byteSize())
      IndexOutOfBoundsException - 如果dstIndex > dstArray.length - elementCount
      IndexOutOfBoundsException - 如果srcOffsetdstIndexelementCount< 0
    • copy

      static void copy(Object srcArray, int srcIndex, MemorySegmentPREVIEW dstSegment, ValueLayoutPREVIEW dstLayout, long dstOffset, int elementCount)
      从源数组复制一定数量的元素到目标内存段。这些元素的大小和对齐约束由给定的布局指定,从源数组的给定索引开始读取,并将其复制到目标段的给定偏移量(以字节表示)。支持的数组类型包括byte[]char[]short[]int[]float[]long[]double[]
      参数:
      srcArray - 源数组。
      srcIndex - 源数组的起始索引。
      dstSegment - 目标段。
      dstLayout - 目标元素布局。如果与布局关联的字节顺序与本机顺序不同,则将对每个数组元素执行字节交换操作。
      dstOffset - 目标段的起始偏移量(以字节为单位)。
      elementCount - 要复制的数组元素数量。
      抛出:
      IllegalStateException - 如果与dstSegment关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得dstSegment().isAccessibleBy(T) == false
      IllegalArgumentException - 如果srcArray不是数组,或者如果它是数组但其类型不受支持。
      IllegalArgumentException - 如果源数组组件类型与srcLayout.carrier()不匹配。
      IllegalArgumentException - 如果offset与源元素布局中的对齐约束不兼容
      IllegalArgumentException - 如果dstLayout.byteAlignment() > dstLayout.byteSize()
      UnsupportedOperationException - 如果dstSegment只读的
      IndexOutOfBoundsException - 如果elementCount * dstLayout.byteSize()溢出。
      IndexOutOfBoundsException - 如果dstOffset > dstSegment.byteSize() - (elementCount * dstLayout.byteSize())
      IndexOutOfBoundsException - 如果srcIndex > srcArray.length - elementCount
      IndexOutOfBoundsException - 如果srcIndexdstOffsetelementCount中有任何一个< 0
    • mismatch

      static long mismatch(MemorySegmentPREVIEW srcSegment, long srcFromOffset, long srcToOffset, MemorySegmentPREVIEW dstSegment, long dstFromOffset, long dstToOffset)
      找到并返回源段和目标段之间第一个不匹配的相对偏移量(以字节为单位)。更具体地说,比较源段中偏移量srcFromOffsetsrcToOffset - 1的字节与目标段中偏移量dstFromOffsetdstToOffset - 1的字节。

      如果两个段在指定范围内共享一个公共前缀,则返回的偏移量是公共前缀的长度,因此在各自段内的相对偏移量处存在不匹配。如果一个段是另一个段的正确前缀,则返回的偏移量是较小的范围,并且相对偏移量仅对具有较大范围的段有效。否则,没有不匹配,返回-1

      参数:
      srcSegment - 源段。
      srcFromOffset - 要测试的源段中第一个字节的偏移量(包括)。
      srcToOffset - 要测试的源段中最后一个字节的偏移量(不包括)。
      dstSegment - 目标段。
      dstFromOffset - 要测试的目标段中第一个字节的偏移量(包括)。
      dstToOffset - 要测试的目标段中最后一个字节的偏移量(不包括)。
      返回:
      源段和目标段之间第一个不匹配的相对偏移量(以字节为单位),否则如果没有不匹配则返回-1。
      抛出:
      IllegalStateException - 如果与srcSegment关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得srcSegment.isAccessibleBy(T) == false
      IllegalStateException - 如果与dstSegment关联的范围不是活动的预览
      WrongThreadException - 如果从线程T调用此方法,使得dstSegment.isAccessibleBy(T) == false
      IndexOutOfBoundsException - 如果srcFromOffset < 0srcToOffset < srcFromOffsetsrcToOffset > srcSegment.byteSize()
      IndexOutOfBoundsException - 如果dstFromOffset < 0dstToOffset < dstFromOffsetdstToOffset > dstSegment.byteSize()
      参见: