8340307: Add explanation around MemorySegment:reinterpret regarding arenas
Reviewed-by: jvernee
This commit is contained in:
parent
8d6cfba37f
commit
646d64e880
@ -761,8 +761,13 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
|||||||
* arena: that is, if the provided arena is a {@linkplain Arena#ofConfined() confined arena},
|
* 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
|
* 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
|
* 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
|
* method returns a segment that can be used as any other segment allocated using the
|
||||||
* provided arena.
|
* 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>
|
* <p>
|
||||||
* Clients can specify an optional cleanup action that should be executed when the
|
* Clients can specify an optional cleanup action that should be executed when the
|
||||||
* provided scope becomes invalid. This cleanup action receives a fresh memory
|
* 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:
|
* compatibly with the confinement restrictions associated with the provided arena:
|
||||||
* that is, if the provided arena is a {@linkplain Arena#ofConfined() confined 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
|
* 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,
|
* of the confinement restrictions associated with this segment. In other words, this
|
||||||
* this method returns a segment that behaves as if it had been allocated using the
|
* method returns a segment that can be used as any other segment allocated using the
|
||||||
* provided arena.
|
* 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>
|
* <p>
|
||||||
* Clients can specify an optional cleanup action that should be executed when the
|
* Clients can specify an optional cleanup action that should be executed when the
|
||||||
* provided scope becomes invalid. This cleanup action receives a fresh memory
|
* provided scope becomes invalid. This cleanup action receives a fresh memory
|
||||||
|
@ -42,6 +42,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||||||
import java.util.function.IntFunction;
|
import java.util.function.IntFunction;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import static java.lang.foreign.ValueLayout.JAVA_BYTE;
|
||||||
import static java.lang.foreign.ValueLayout.JAVA_INT;
|
import static java.lang.foreign.ValueLayout.JAVA_INT;
|
||||||
import static org.testng.Assert.*;
|
import static org.testng.Assert.*;
|
||||||
|
|
||||||
@ -392,6 +393,24 @@ public class TestSegments {
|
|||||||
assertEquals(counter.get(), 3);
|
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
|
@Test
|
||||||
void testThrowInCleanup() {
|
void testThrowInCleanup() {
|
||||||
AtomicInteger counter = new AtomicInteger();
|
AtomicInteger counter = new AtomicInteger();
|
||||||
|
Loading…
Reference in New Issue
Block a user