- 所有超级接口:
-
AutoCloseable
,SegmentAllocator预览
Arena
是Java平台的预览API。
一个arena具有一个scope预览 - arena scope。由arena分配的所有段都与arena scope相关联。因此,arena确定了由其分配的所有内存段的时间范围。
此外,arena还确定由其分配的内存段是否应该对特定线程受限制预览。arena是一个SegmentAllocator
预览,具有几种分配方法,客户端可以使用这些方法来获取本机段。
最简单的arena是全局arena。全局arena具有无限的生命周期。因此,使用全局arena分配的本机段始终可访问,并且它们的内存后备区域永远不会被释放。此外,使用全局arena分配的内存段可以从任何线程访问预览。
MemorySegment segment = Arena.global().allocate(100, 1);
...
// 段永远不会被释放!
另外,客户端可以获取一个自动arena,即由垃圾回收器自动管理生命周期的arena。因此,使用自动arena分配的内存段的内存后备区域将在自动arena(及其分配的所有段)变为不可达后的某个不确定时间之后被释放,如下所示:
MemorySegment segment = Arena.ofAuto().allocate(100, 1);
...
segment = null; // 在此点之后,段区域变为可释放
客户端通常希望控制内存段的释放时间,而不是将释放时间留给Java运行时。两种类型的arena支持这一点,即受限制和共享 arena。它们都具有手动管理的有界生命周期。例如,受限制arena的生命周期从创建受限制arena开始,到关闭受限制arena结束。因此,使用受限制arena分配的内存段在关闭受限制arena时被释放。在这种情况下,使用受限制arena分配的所有段都将无效,并且对这些段进行的后续访问操作将导致IllegalStateException
异常:
MemorySegment segment = null;
try (Arena arena = Arena.ofConfined()) {
segment = arena.allocate(100);
...
} // 段区域在此处被释放
segment.get(ValueLayout.JAVA_BYTE, 0); // 抛出IllegalStateException
各种arena的特征总结在以下表中:
类型 有界生命周期 可显式关闭 可从多个线程访问 全局 否 否 是 自动 是 否 是 受限制 是 是 否 共享 是 是 是
安全性和线程限制
Arenas提供强大的时间安全保证:由arena分配的内存段在arena关闭后无法访问。提供此保证的成本取决于可以访问由arena分配的内存段的线程数量。例如,如果一个arena总是由一个线程创建和关闭,并且由该相同线程始终访问由arena分配的内存段,则确保正确性是微不足道的。相反,如果一个arena分配的段可以被多个线程访问,或者如果可以由非访问线程关闭arena,则确保正确性就复杂得多。例如,使用arena分配的段可能在另一个线程尝试同时关闭arena的情况下被访问。为了提供强大的时间安全保证,而不强迫每个客户端,甚至是简单的客户端,承担性能影响,arenas被分为线程限制 arenas和共享 arenas。
受限制的arenas支持强大的线程限制保证。创建时,它们被分配一个所有者线程,通常是启动创建操作的线程。受限制arena创建的段只能由所有者线程访问预览。此外,任何尝试从非所有者线程关闭受限制arena的操作将导致WrongThreadException
异常。
另一方面,共享arenas没有所有者线程。共享arena创建的段可以被任何线程访问预览。当多个线程需要同时访问相同的内存段时(例如在并行处理的情况下),这可能很有用。此外,任何线程都可以关闭共享arena。
自定义arenas
客户端可以定义自定义arenas来实现更高效的分配策略,或者更好地控制arena何时(以及由谁)可以关闭。例如,以下代码定义了一个切片arena,其行为类似于受限制arena(即,单线程访问),但在内部使用切片分配器预览来响应分配请求。当切片arena关闭时,底层受限制arena也将关闭;这将使所有使用切片arena分配的段无效(因为切片arena的范围与底层受限制arena的范围相同):class SlicingArena implements Arena {
final Arena arena = Arena.ofConfined();
final SegmentAllocator slicingAllocator;
SlicingArena(long size) {
slicingAllocator = SegmentAllocator.slicingAllocator(arena.allocate(size));
}
public MemorySegment allocate(long byteSize, long byteAlignment) {
return slicingAllocator.allocate(byteSize, byteAlignment);
}
public MemorySegment.Scope scope() {
return arena.scope();
}
public void close() {
arena.close();
}
}
try (Arena slicingArena = new SlicingArena(1000)) {
for (int i = 0; i < 10; i++) {
MemorySegment s = slicingArena.allocateArray(JAVA_INT, 1, 2, 3, 4, 5);
...
}
} // 所有分配的内存在此释放
- 实现要求:
- 此接口的实现是线程安全的。
- 自:
- 20
- 另请参阅:
-
Method Summary
Methods declared in interface java.lang.foreign.SegmentAllocatorPREVIEW
allocate, allocate, allocate, allocate, allocate, allocate, allocate, allocate, allocate, allocate, allocateArray, allocateArray, allocateArray, allocateArray, allocateArray, allocateArray, allocateArray, allocateArray, allocateUtf8String
-
Method Details
-
ofAuto
- 返回:
- 一个由垃圾回收器自动管理的新区域。
-
global
- 返回:
- 全局区域。
-
ofConfined
- 返回:
- 一个新的受限区域
-
allocate
- 指定者:
-
allocate
在接口SegmentAllocator预览
- 实现要求:
-
此方法的实现必须返回具有请求大小并与提供的对齐约束兼容的本机段。此外,对于此方法返回的任何两个段
S1, S2
,必须满足以下不变式:S1.asOverlappingSlice(S2).isEmpty() == true
- 参数:
-
byteSize
- 本机内存段支持的堆外内存区域的大小(以字节为单位)。 -
byteAlignment
- 本机内存段支持的堆外内存区域的对齐约束(以字节为单位)。 - 返回:
- 一个新的本机内存段。
- 抛出:
-
IllegalArgumentException
- 如果bytesSize < 0
,byteAlignment <= 0
,或者byteAlignment
不是2的幂。 -
IllegalStateException
- 如果此区域已经被关闭。 -
WrongThreadException
- 如果此区域是受限的,并且从非区域所有者线程调用此方法。
-
scope
MemorySegment.ScopePREVIEW scope()返回区域范围。- 返回:
- 区域范围
-
close
void close()- 指定者:
-
close
在接口AutoCloseable
- API 注意:
- 此操作不是幂等的;也就是说,关闭已经关闭的区域总是会导致抛出异常。这反映了一个故意的设计选择:未能关闭区域可能会揭示底层应用程序逻辑中的错误。
- 实现要求:
-
如果此方法正常完成,则
this.scope().isAlive() == false
。如果不支持显式关闭操作,实现可以抛出UnsupportedOperationException
。 - 抛出:
-
IllegalStateException
- 如果区域已经被关闭。 -
IllegalStateException
- 如果与此区域关联的段正在被并发访问,例如通过downcall方法句柄预览。 -
WrongThreadException
- 如果此区域是受限的,并且从非区域所有者线程调用此方法。 -
UnsupportedOperationException
- 如果无法显式关闭此区域。 - 另请参阅:
-
Arena
。