From d13302f8b06f65319426a25a9368abaf72f3c247 Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Mon, 11 Dec 2023 07:52:31 +0000 Subject: [PATCH] 8321387: SegmentAllocator:allocateFrom(AddressLayout, MemorySegment) does not throw stated UnsupportedOperationException Reviewed-by: mcimadamore --- .../java/lang/foreign/MemoryLayout.java | 3 ++ .../java/lang/foreign/MemorySegment.java | 52 +++++++++++-------- .../java/lang/foreign/SegmentAllocator.java | 18 +++++-- .../foreign/AbstractMemorySegmentImpl.java | 2 +- test/jdk/java/foreign/TestArrayCopy.java | 5 +- test/jdk/java/foreign/TestMemoryAccess.java | 6 +-- .../foreign/TestMemoryAccessInstance.java | 1 - .../java/foreign/TestSegmentAllocators.java | 29 +++++++++++ test/jdk/java/foreign/TestSegmentCopy.java | 11 +++- test/jdk/java/foreign/TestSegments.java | 8 ++- 10 files changed, 99 insertions(+), 36 deletions(-) diff --git a/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java b/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java index 0933c637acb..321d9b09bad 100644 --- a/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java @@ -631,6 +631,9 @@ public sealed interface MemoryLayout *
  • The accessed memory segment must be * {@link MemorySegment#isAccessibleBy(Thread) accessible} from the thread * performing the access operation, or a {@link WrongThreadException} is thrown.
  • + *
  • For write operations, the accessed memory segment must not be + * {@link MemorySegment#isReadOnly() read only}, or an + * {@link IllegalArgumentException} is thrown.
  • *
  • The {@linkplain MemorySegment#scope() scope} associated with the accessed * segment must be {@linkplain MemorySegment.Scope#isAlive() alive}, or an * {@link IllegalStateException} is thrown.
  • diff --git a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java index 0b0a2e136cb..da255b9912b 100644 --- a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java +++ b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java @@ -869,7 +869,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * this segment is not {@linkplain Scope#isAlive() alive} * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false} - * @throws UnsupportedOperationException if this segment is + * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} */ MemorySegment fill(byte value); @@ -894,7 +894,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * {@code src} is not {@linkplain Scope#isAlive() alive} * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code src.isAccessibleBy(T) == false} - * @throws UnsupportedOperationException if this segment is + * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} * @return this segment */ @@ -1269,6 +1269,8 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * this segment is not {@linkplain Scope#isAlive() alive} * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false} + * @throws IllegalArgumentException if this segment is + * {@linkplain #isReadOnly() read-only} */ void setString(long offset, String str); @@ -1306,6 +1308,8 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * such that {@code isAccessibleBy(T) == false} * @throws IllegalArgumentException if {@code charset} is not a * {@linkplain StandardCharsets standard charset} + * @throws IllegalArgumentException if this segment is + * {@linkplain #isReadOnly() read-only} */ void setString(long offset, String str, Charset charset); @@ -1493,7 +1497,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * @throws IndexOutOfBoundsException if {@code dstOffset > dstSegment.byteSize() - bytes} * @throws IndexOutOfBoundsException if either {@code srcOffset}, * {@code dstOffset} or {@code bytes} are {@code < 0} - * @throws UnsupportedOperationException if {@code dstSegment} is + * @throws IllegalArgumentException if {@code dstSegment} is * {@linkplain #isReadOnly() read-only} */ @ForceInline @@ -1552,7 +1556,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * {@code dstSegment} is not {@linkplain Scope#isAlive() alive} * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code dstSegment.isAccessibleBy(T) == false} - * @throws UnsupportedOperationException if {@code dstSegment} is {@linkplain #isReadOnly() read-only} + * @throws IllegalArgumentException if {@code dstSegment} is {@linkplain #isReadOnly() read-only} * @throws IndexOutOfBoundsException if {@code elementCount * srcLayout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code elementCount * dtsLayout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code srcOffset > srcSegment.byteSize() - (elementCount * srcLayout.byteSize())} @@ -1605,7 +1609,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} - * @throws UnsupportedOperationException if this segment is + * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} */ void set(ValueLayout.OfByte layout, long offset, byte value); @@ -1643,7 +1647,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} - * @throws UnsupportedOperationException if this segment is + * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} */ void set(ValueLayout.OfBoolean layout, long offset, boolean value); @@ -1681,7 +1685,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} - * @throws UnsupportedOperationException if this segment is + * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} */ void set(ValueLayout.OfChar layout, long offset, char value); @@ -1719,7 +1723,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} - * @throws UnsupportedOperationException if this segment is + * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} */ void set(ValueLayout.OfShort layout, long offset, short value); @@ -1757,7 +1761,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} - * @throws UnsupportedOperationException if this segment is + * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} */ void set(ValueLayout.OfInt layout, long offset, int value); @@ -1795,7 +1799,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} - * @throws UnsupportedOperationException if this segment is + * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} */ void set(ValueLayout.OfFloat layout, long offset, float value); @@ -1833,7 +1837,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} - * @throws UnsupportedOperationException if this segment is + * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} */ void set(ValueLayout.OfLong layout, long offset, long value); @@ -1871,7 +1875,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} - * @throws UnsupportedOperationException if this segment is + * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} */ void set(ValueLayout.OfDouble layout, long offset, double value); @@ -1921,8 +1925,10 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} * @throws UnsupportedOperationException if this segment is * {@linkplain #isReadOnly() read-only} - * @throws UnsupportedOperationException if {@code value} is not a + * @throws IllegalArgumentException if {@code value} is not a * {@linkplain #isNative() native} segment + * @throws IllegalArgumentException if this segment is + * {@linkplain #isReadOnly() read-only} */ void set(AddressLayout layout, long offset, MemorySegment value); @@ -2055,7 +2061,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} - * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only} + * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only} */ void setAtIndex(ValueLayout.OfByte layout, long index, byte value); @@ -2078,7 +2084,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} - * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only} + * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only} */ void setAtIndex(ValueLayout.OfBoolean layout, long index, boolean value); @@ -2101,7 +2107,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} - * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only} + * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only} */ void setAtIndex(ValueLayout.OfShort layout, long index, short value); @@ -2146,7 +2152,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} - * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only} + * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only} */ void setAtIndex(ValueLayout.OfInt layout, long index, int value); @@ -2191,7 +2197,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} - * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only} + * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only} */ void setAtIndex(ValueLayout.OfFloat layout, long index, float value); @@ -2236,7 +2242,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} - * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only} + * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only} */ void setAtIndex(ValueLayout.OfLong layout, long index, long value); @@ -2281,7 +2287,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} - * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only} + * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only} */ void setAtIndex(ValueLayout.OfDouble layout, long index, double value); @@ -2336,7 +2342,9 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only} - * @throws UnsupportedOperationException if {@code value} is not a {@linkplain #isNative() native} segment + * @throws IllegalArgumentException if {@code value} is not a {@linkplain #isNative() native} segment + * @throws IllegalArgumentException if this segment is + * {@linkplain #isReadOnly() read-only} */ void setAtIndex(AddressLayout layout, long index, MemorySegment value); @@ -2460,7 +2468,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * incompatible with the alignment constraint * in the source element layout * @throws IllegalArgumentException if {@code dstLayout.byteAlignment() > dstLayout.byteSize()} - * @throws UnsupportedOperationException if {@code dstSegment} is {@linkplain #isReadOnly() read-only} + * @throws IllegalArgumentException if {@code dstSegment} is {@linkplain #isReadOnly() read-only} * @throws IndexOutOfBoundsException if {@code elementCount * dstLayout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code dstOffset > dstSegment.byteSize() - (elementCount * dstLayout.byteSize())} * @throws IndexOutOfBoundsException if {@code srcIndex > srcArray.length - elementCount} diff --git a/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java b/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java index a4977d62d00..6be9d949ea6 100644 --- a/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java +++ b/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java @@ -350,7 +350,7 @@ public interface SegmentAllocator { * * @param layout the layout of the block of memory to be allocated * @param value the value to be set in the newly allocated memory segment - * @throws UnsupportedOperationException if {@code value} is not + * @throws IllegalArgumentException if {@code value} is not * a {@linkplain MemorySegment#isNative() native} segment */ default MemorySegment allocateFrom(AddressLayout layout, MemorySegment value) { @@ -670,9 +670,11 @@ public interface SegmentAllocator { * * @param segment the segment from which the returned allocator should slice from * @return a new slicing allocator + * @throws IllegalArgumentException if the {@code segment} is + * {@linkplain MemorySegment#isReadOnly() read-only} */ static SegmentAllocator slicingAllocator(MemorySegment segment) { - Objects.requireNonNull(segment); + assertWritable(segment); return new SlicingAllocator(segment); } @@ -700,9 +702,19 @@ public interface SegmentAllocator { * @param segment the memory segment to be recycled by the returned allocator * @return an allocator that recycles an existing segment upon each new * allocation request + * @throws IllegalArgumentException if the {@code segment} is + * {@linkplain MemorySegment#isReadOnly() read-only} */ static SegmentAllocator prefixAllocator(MemorySegment segment) { - return (AbstractMemorySegmentImpl)Objects.requireNonNull(segment); + assertWritable(segment); + return (AbstractMemorySegmentImpl)segment; + } + + private static void assertWritable(MemorySegment segment) { + // Implicit null check + if (segment.isReadOnly()) { + throw new IllegalArgumentException("read-only segment"); + } } @ForceInline diff --git a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java index 2f902e57ee5..305594952d4 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java @@ -361,7 +361,7 @@ public abstract sealed class AbstractMemorySegmentImpl @ForceInline public void checkAccess(long offset, long length, boolean readOnly) { if (!readOnly && this.readOnly) { - throw new UnsupportedOperationException("Attempt to write a read-only segment"); + throw new IllegalArgumentException("Attempt to write a read-only segment"); } checkBounds(offset, length); } diff --git a/test/jdk/java/foreign/TestArrayCopy.java b/test/jdk/java/foreign/TestArrayCopy.java index 0a04f00e4f5..9a1c48a394e 100644 --- a/test/jdk/java/foreign/TestArrayCopy.java +++ b/test/jdk/java/foreign/TestArrayCopy.java @@ -26,12 +26,9 @@ * @run testng TestArrayCopy */ -import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; -import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; import java.lang.invoke.VarHandle; import java.nio.ByteOrder; import java.util.ArrayList; @@ -240,7 +237,7 @@ public class TestArrayCopy { try { helper.copyFromArray(srcArr, 0, SEG_LENGTH_BYTES / bytesPerElement, dstSeg, 0, ByteOrder.nativeOrder()); fail(); - } catch (UnsupportedOperationException ex) { + } catch (IllegalArgumentException ex) { //ok } } diff --git a/test/jdk/java/foreign/TestMemoryAccess.java b/test/jdk/java/foreign/TestMemoryAccess.java index 19f480aa4b2..ded9be1c085 100644 --- a/test/jdk/java/foreign/TestMemoryAccess.java +++ b/test/jdk/java/foreign/TestMemoryAccess.java @@ -87,7 +87,7 @@ public class TestMemoryAccess { if (isRO) { throw new AssertionError(); //not ok, memory should be immutable } - } catch (UnsupportedOperationException ex) { + } catch (IllegalArgumentException ex) { if (!isRO) { throw new AssertionError(); //we should not have failed! } @@ -121,7 +121,7 @@ public class TestMemoryAccess { if (isRO) { throw new AssertionError(); //not ok, memory should be immutable } - } catch (UnsupportedOperationException ex) { + } catch (IllegalArgumentException ex) { if (!isRO) { throw new AssertionError(); //we should not have failed! } @@ -185,7 +185,7 @@ public class TestMemoryAccess { if (isRO) { throw new AssertionError(); //not ok, memory should be immutable } - } catch (UnsupportedOperationException ex) { + } catch (IllegalArgumentException ex) { if (!isRO) { throw new AssertionError(); //we should not have failed! } diff --git a/test/jdk/java/foreign/TestMemoryAccessInstance.java b/test/jdk/java/foreign/TestMemoryAccessInstance.java index a1c774b72dd..d56f44388a4 100644 --- a/test/jdk/java/foreign/TestMemoryAccessInstance.java +++ b/test/jdk/java/foreign/TestMemoryAccessInstance.java @@ -27,7 +27,6 @@ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_SEGMENT_FORCE_EXACT=true --enable-native-access=ALL-UNNAMED TestMemoryAccessInstance */ -import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; import java.lang.foreign.Arena; import java.lang.foreign.ValueLayout; diff --git a/test/jdk/java/foreign/TestSegmentAllocators.java b/test/jdk/java/foreign/TestSegmentAllocators.java index 48e09f647c9..0e0c49320da 100644 --- a/test/jdk/java/foreign/TestSegmentAllocators.java +++ b/test/jdk/java/foreign/TestSegmentAllocators.java @@ -100,6 +100,16 @@ public class TestSegmentAllocators { static final int SIZE_256M = 1024 * 1024 * 256; + @Test(expectedExceptions = IllegalArgumentException.class) + public void testReadOnlySlicingAllocator() { + SegmentAllocator.slicingAllocator(MemorySegment.ofArray(new int[0]).asReadOnly()); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testReadOnlyPrefixAllocator() { + SegmentAllocator.prefixAllocator(MemorySegment.ofArray(new int[0]).asReadOnly()); + } + @Test public void testBigAllocationInUnboundedSession() { try (Arena arena = Arena.ofConfined()) { @@ -160,6 +170,25 @@ public class TestSegmentAllocators { } } + @Test(expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = ".*Heap segment not allowed.*") + public void testArenaAllocateFromHeapSegment() { + try (Arena arena = Arena.ofConfined()) { + var heapSegment = MemorySegment.ofArray(new int[]{1}); + arena.allocateFrom(ValueLayout.ADDRESS, heapSegment); + } + } + + @Test(expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = ".*Heap segment not allowed.*") + public void testAllocatorAllocateFromHeapSegment() { + try (Arena arena = Arena.ofConfined()) { + SegmentAllocator allocator = SegmentAllocator.prefixAllocator(arena.allocate(16)); + var heapSegment = MemorySegment.ofArray(new int[]{1}); + allocator.allocateFrom(ValueLayout.ADDRESS, heapSegment); + } + } + @Test public void testArrayAllocateDelegation() { AtomicInteger calls = new AtomicInteger(); diff --git a/test/jdk/java/foreign/TestSegmentCopy.java b/test/jdk/java/foreign/TestSegmentCopy.java index 85f843eddd7..414cd0a8451 100644 --- a/test/jdk/java/foreign/TestSegmentCopy.java +++ b/test/jdk/java/foreign/TestSegmentCopy.java @@ -76,7 +76,7 @@ public class TestSegmentCopy { } } - @Test(expectedExceptions = UnsupportedOperationException.class, dataProvider = "segmentKinds") + @Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "segmentKinds") public void testReadOnlyCopy(SegmentKind kind1, SegmentKind kind2) { MemorySegment s1 = kind1.makeSegment(TEST_BYTE_SIZE); MemorySegment s2 = kind2.makeSegment(TEST_BYTE_SIZE); @@ -84,6 +84,15 @@ public class TestSegmentCopy { MemorySegment.copy(s1, Type.BYTE.layout, 0, s2.asReadOnly(), Type.BYTE.layout, 0, 0); } + @Test(expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = ".*Attempt to write a read-only segment.*") + public void badCopy6Arg() { + try (Arena scope = Arena.ofConfined()) { + MemorySegment dest = scope.allocate(ValueLayout.JAVA_INT).asReadOnly(); + MemorySegment.copy(new int[1],0, dest, ValueLayout.JAVA_INT, 0 ,1); // should throw + } + } + @Test(expectedExceptions = IndexOutOfBoundsException.class, dataProvider = "types") public void testBadOverflow(Type type) { if (type.layout.byteSize() > 1) { diff --git a/test/jdk/java/foreign/TestSegments.java b/test/jdk/java/foreign/TestSegments.java index 940d96e844d..94b49eb7e59 100644 --- a/test/jdk/java/foreign/TestSegments.java +++ b/test/jdk/java/foreign/TestSegments.java @@ -325,12 +325,18 @@ public class TestSegments { assertEquals(segment.scope(), arena.scope()); } - @Test(dataProvider = "segmentFactories", expectedExceptions = UnsupportedOperationException.class) + @Test(dataProvider = "segmentFactories", expectedExceptions = IllegalArgumentException.class) public void testFillIllegalAccessMode(Supplier segmentSupplier) { MemorySegment segment = segmentSupplier.get(); segment.asReadOnly().fill((byte) 0xFF); } + @Test(dataProvider = "segmentFactories", expectedExceptions = IllegalArgumentException.class) + public void testFromStringIllegalAccessMode(Supplier segmentSupplier) { + MemorySegment segment = segmentSupplier.get(); + segment.asReadOnly().setString(0, "a"); + } + @Test(dataProvider = "segmentFactories") public void testFillThread(Supplier segmentSupplier) throws Exception { MemorySegment segment = segmentSupplier.get();