8340307: Add explanation around MemorySegment:reinterpret regarding arenas

Reviewed-by: jvernee
This commit is contained in:
Per Minborg 2024-11-04 14:12:30 +00:00
parent 8d6cfba37f
commit 646d64e880
2 changed files with 34 additions and 5 deletions

View File

@ -761,8 +761,13 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* arena: that is, if the provided arena is a {@linkplain Arena#ofConfined() confined arena},
* the returned segment can only be accessed by the arena's owner thread, regardless
* of the confinement restrictions associated with this segment. In other words, this
* method returns a segment that behaves as if it had been allocated using the
* provided arena.
* method returns a segment that can be used as any other segment allocated using the
* provided arena. However, The returned segment is backed by the same memory region
* as that of the original segment. As such, the region of memory backing the
* returned segment is deallocated only when this segment's arena is closed.
* This might lead to <em>use-after-free</em> issues, as the returned segment can be
* accessed <em>after</em> its region of memory has been deallocated via this
* segment's arena.
* <p>
* Clients can specify an optional cleanup action that should be executed when the
* provided scope becomes invalid. This cleanup action receives a fresh memory
@ -811,9 +816,14 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* compatibly with the confinement restrictions associated with the provided arena:
* that is, if the provided arena is a {@linkplain Arena#ofConfined() confined arena},
* the returned segment can only be accessed by the arena's owner thread, regardless
* of the confinement restrictions associated with this segment. In other words,
* this method returns a segment that behaves as if it had been allocated using the
* provided arena.
* of the confinement restrictions associated with this segment. In other words, this
* method returns a segment that can be used as any other segment allocated using the
* provided arena. However, The returned segment is backed by the same memory region
* as that of the original segment. As such, the region of memory backing the
* returned segment is deallocated only when this segment's arena is closed.
* This might lead to <em>use-after-free</em> issues, as the returned segment can be
* accessed <em>after</em> its region of memory has been deallocated via this
* segment's arena.
* <p>
* Clients can specify an optional cleanup action that should be executed when the
* provided scope becomes invalid. This cleanup action receives a fresh memory

View File

@ -42,6 +42,7 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.function.IntFunction;
import java.util.function.Supplier;
import static java.lang.foreign.ValueLayout.JAVA_BYTE;
import static java.lang.foreign.ValueLayout.JAVA_INT;
import static org.testng.Assert.*;
@ -392,6 +393,24 @@ public class TestSegments {
assertEquals(counter.get(), 3);
}
@Test
void testReinterpretArenaClose() {
MemorySegment segment;
try (Arena arena = Arena.ofConfined()){
try (Arena otherArena = Arena.ofConfined()) {
segment = arena.allocate(100);
segment = segment.reinterpret(otherArena, null);
}
final MemorySegment sOther = segment;
assertThrows(IllegalStateException.class, () -> sOther.get(JAVA_BYTE, 0));
segment = segment.reinterpret(arena, null);
final MemorySegment sOriginal = segment;
sOriginal.get(JAVA_BYTE, 0);
}
final MemorySegment closed = segment;
assertThrows(IllegalStateException.class, () -> closed.get(JAVA_BYTE, 0));
}
@Test
void testThrowInCleanup() {
AtomicInteger counter = new AtomicInteger();