/* * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ /* * @test * @modules java.base/jdk.internal.foreign * @run testng/othervm TestSegmentAllocators */ import java.lang.foreign.*; import org.testng.annotations.*; import java.lang.foreign.Arena; import java.lang.invoke.VarHandle; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.CharBuffer; import java.nio.DoubleBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.LongBuffer; import java.nio.ShortBuffer; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiFunction; import java.util.function.Function; import static org.testng.Assert.*; public class TestSegmentAllocators { final static int ELEMS = 128; @Test(dataProvider = "scalarAllocations") @SuppressWarnings("unchecked") public void testAllocation(Z value, AllocationFactory allocationFactory, L layout, AllocationFunction allocationFunction, Function handleFactory) { layout = (L)layout.withByteAlignment(layout.byteSize()); L[] layouts = (L[])new ValueLayout[] { layout, layout.withByteAlignment(layout.byteAlignment() * 2), layout.withByteAlignment(layout.byteAlignment() * 4), layout.withByteAlignment(layout.byteAlignment() * 8) }; for (L alignedLayout : layouts) { List addressList = new ArrayList<>(); int elems = ELEMS / ((int)alignedLayout.byteAlignment() / (int)layout.byteAlignment()); Arena[] arenas = { Arena.ofConfined(), Arena.ofShared() }; for (Arena arena : arenas) { try (arena) { SegmentAllocator allocator = allocationFactory.allocator(alignedLayout.byteSize() * ELEMS, arena); for (int i = 0; i < elems; i++) { MemorySegment address = allocationFunction.allocate(allocator, alignedLayout, value); assertEquals(address.byteSize(), alignedLayout.byteSize()); addressList.add(address); VarHandle handle = handleFactory.apply(alignedLayout); assertEquals(value, handle.get(address, 0L)); } boolean isBound = allocationFactory.isBound(); try { allocationFunction.allocate(allocator, alignedLayout, value); assertFalse(isBound); } catch (IndexOutOfBoundsException ex) { //failure is expected if bound assertTrue(isBound); } } // addresses should be invalid now for (MemorySegment address : addressList) { assertFalse(address.scope().isAlive()); } } } } 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()) { for (int i = 8 ; i < SIZE_256M ; i *= 8) { SegmentAllocator allocator = SegmentAllocator.slicingAllocator(arena.allocate(i * 2 + 1)); MemorySegment address = allocator.allocate(i, i); //check size assertEquals(address.byteSize(), i); //check alignment assertEquals(address.address() % i, 0); } } } @Test public void testTooBigForBoundedArena() { try (Arena arena = Arena.ofConfined()) { SegmentAllocator allocator = SegmentAllocator.slicingAllocator(arena.allocate(10)); assertThrows(IndexOutOfBoundsException.class, () -> allocator.allocate(12)); allocator.allocate(5); } } @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class) public void testBadAllocationSize(SegmentAllocator allocator) { allocator.allocate(-1); } @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class) public void testBadAllocationAlignZero(SegmentAllocator allocator) { allocator.allocate(1, 0); } @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class) public void testBadAllocationAlignNeg(SegmentAllocator allocator) { allocator.allocate(1, -1); } @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class) public void testBadAllocationAlignNotPowerTwo(SegmentAllocator allocator) { allocator.allocate(1, 3); } @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class) public void testBadAllocationArrayNegSize(SegmentAllocator allocator) { allocator.allocate(ValueLayout.JAVA_BYTE, -1); } @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class) public void testBadAllocationArrayOverflow(SegmentAllocator allocator) { allocator.allocate(ValueLayout.JAVA_LONG, Long.MAX_VALUE); } @Test(expectedExceptions = OutOfMemoryError.class) public void testBadArenaNullReturn() { try (Arena arena = Arena.ofConfined()) { arena.allocate(Long.MAX_VALUE, 2); } } @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); } } // Invariant checking tests for the SegmentAllocator method: // MemorySegment allocateFrom(ValueLayout elementLayout, // MemorySegment source, // ValueLayout sourceElementLayout, // long sourceOffset, // long elementCount) { @Test public void testAllocatorAllocateFromArguments() { try (Arena arena = Arena.ofConfined()) { var sourceElements = 2; var source = arena.allocate(ValueLayout.JAVA_LONG, sourceElements); var elementLayout = ValueLayout.JAVA_INT; var sourceElementLayout = ValueLayout.JAVA_INT; // IllegalArgumentException if {@code elementLayout.byteSize() != sourceElementLayout.byteSize()} assertThrows(IllegalArgumentException.class, () -> arena.allocateFrom(elementLayout, source, ValueLayout.JAVA_BYTE, 0, 1) ); // IllegalArgumentException if source segment/offset // are incompatible with the alignment constraint // in the source element layout assertThrows(IllegalArgumentException.class, () -> arena.allocateFrom(elementLayout, source.asSlice(1), sourceElementLayout, 0, 1) ); assertThrows(IllegalArgumentException.class, () -> arena.allocateFrom(elementLayout, source, sourceElementLayout, 1, 1) ); // IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()} assertThrows(IllegalArgumentException.class, () -> arena.allocateFrom(elementLayout.withByteAlignment(elementLayout.byteAlignment() * 2), source, sourceElementLayout, 1, 1) ); // IllegalStateException if the {@linkplain MemorySegment#scope() scope} associated // with {@code source} is not {@linkplain MemorySegment.Scope#isAlive() alive} // This is tested in TestScopedOperations // WrongThreadException if this method is called from a thread {@code T}, // such that {@code source.isAccessibleBy(T) == false} CompletableFuture future = CompletableFuture.supplyAsync(Arena::ofConfined); try { Arena otherThreadArena = future.get(); assertThrows(WrongThreadException.class, () -> otherThreadArena.allocateFrom(elementLayout, source, sourceElementLayout, 0, 1) ); } catch (ExecutionException | InterruptedException e) { fail("Unable to create arena", e); } // IllegalArgumentException if {@code elementCount * sourceElementLayout.byteSize()} overflows assertThrows(IllegalArgumentException.class, () -> arena.allocateFrom(elementLayout, source, sourceElementLayout, 0, Long.MAX_VALUE) ); // IndexOutOfBoundsException if {@code sourceOffset > source.byteSize() - (elementCount * sourceElementLayout.byteSize())} assertThrows(IndexOutOfBoundsException.class, () -> arena.allocateFrom(elementLayout, source, sourceElementLayout, source.byteSize() - (1 * sourceElementLayout.byteAlignment()) + elementLayout.byteSize(), 1) ); // IndexOutOfBoundsException if {@code sourceOffset < 0} assertThrows(IndexOutOfBoundsException.class, () -> arena.allocateFrom(elementLayout, source, sourceElementLayout, -elementLayout.byteSize(), 1) ); // IllegalArgumentException if {@code elementCount < 0} assertThrows(IllegalArgumentException.class, () -> arena.allocateFrom(elementLayout, source, sourceElementLayout, 0, -1) ); } } @Test public void testArrayAllocateDelegation() { AtomicInteger calls = new AtomicInteger(); SegmentAllocator allocator = new SegmentAllocator() { @Override public MemorySegment allocate(long bytesSize, long byteAlignment) { return MemorySegment.NULL; } @Override public MemorySegment allocateFrom(ValueLayout elementLayout, MemorySegment source, ValueLayout sourceElementLayout, long sourceOffset, long elementCount) { calls.incrementAndGet(); return MemorySegment.NULL; } }; allocator.allocateFrom(ValueLayout.JAVA_BYTE); allocator.allocateFrom(ValueLayout.JAVA_SHORT); allocator.allocateFrom(ValueLayout.JAVA_CHAR); allocator.allocateFrom(ValueLayout.JAVA_INT); allocator.allocateFrom(ValueLayout.JAVA_FLOAT); allocator.allocateFrom(ValueLayout.JAVA_LONG); allocator.allocateFrom(ValueLayout.JAVA_DOUBLE); assertEquals(calls.get(), 7); } @Test public void testStringAllocateDelegation() { AtomicInteger calls = new AtomicInteger(); SegmentAllocator allocator = new SegmentAllocator() { @Override public MemorySegment allocate(long byteSize, long byteAlignment) { return Arena.ofAuto().allocate(byteSize, byteAlignment); } @Override public MemorySegment allocate(long size) { calls.incrementAndGet(); return allocate(size, 1); }; }; allocator.allocateFrom("Hello"); assertEquals(calls.get(), 1); } @Test(dataProvider = "arrayAllocations") public void testArray(AllocationFactory allocationFactory, ValueLayout layout, AllocationFunction allocationFunction, ToArrayHelper arrayHelper) { Z arr = arrayHelper.array(); Arena[] arenas = { Arena.ofConfined(), Arena.ofShared() }; for (Arena arena : arenas) { try (arena) { SegmentAllocator allocator = allocationFactory.allocator(100, arena); MemorySegment address = allocationFunction.allocate(allocator, layout, arr); Z found = arrayHelper.toArray(address, layout); assertEquals(found, arr); } } } @Test(dataProvider = "arrayAllocations") public void testPredicatesAndCommands(AllocationFactory allocationFactory, ValueLayout layout, AllocationFunction allocationFunction, ToArrayHelper arrayHelper) { Z arr = arrayHelper.array(); Arena[] arenas = { Arena.ofConfined(), Arena.ofShared() }; for (Arena arena : arenas) { try (arena) { SegmentAllocator allocator = allocationFactory.allocator(100, arena); MemorySegment segment = allocationFunction.allocate(allocator, layout, arr); assertThrows(UnsupportedOperationException.class, segment::load); assertThrows(UnsupportedOperationException.class, segment::unload); assertThrows(UnsupportedOperationException.class, segment::isLoaded); assertThrows(UnsupportedOperationException.class, segment::force); assertFalse(segment.isMapped()); assertTrue(segment.isNative()); } } } @DataProvider(name = "scalarAllocations") static Object[][] scalarAllocations() { List scalarAllocations = new ArrayList<>(); for (AllocationFactory factory : AllocationFactory.values()) { scalarAllocations.add(new Object[] { (byte)42, factory, ValueLayout.JAVA_BYTE, (AllocationFunction.OfByte) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { (short)42, factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfShort) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { (char)42, factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfChar) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { 42, factory, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfInt) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { 42f, factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfFloat) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { 42L, factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfLong) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { 42d, factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfDouble) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { MemorySegment.ofAddress(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfAddress) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { (short)42, factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), (AllocationFunction.OfShort) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { (char)42, factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), (AllocationFunction.OfChar) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { 42, factory, ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), (AllocationFunction.OfInt) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { 42f, factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), (AllocationFunction.OfFloat) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { 42L, factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), (AllocationFunction.OfLong) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { 42d, factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), (AllocationFunction.OfDouble) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { MemorySegment.ofAddress(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfAddress) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); } return scalarAllocations.toArray(Object[][]::new); } @DataProvider(name = "arrayAllocations") static Object[][] arrayAllocations() { List arrayAllocations = new ArrayList<>(); for (AllocationFactory factory : AllocationFactory.values()) { arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_BYTE, (AllocationFunction.OfByteArray) SegmentAllocator::allocateFrom, ToArrayHelper.toByteArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), (AllocationFunction.OfCharArray) SegmentAllocator::allocateFrom, ToArrayHelper.toCharArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), (AllocationFunction.OfShortArray) SegmentAllocator::allocateFrom, ToArrayHelper.toShortArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), (AllocationFunction.OfIntArray) SegmentAllocator::allocateFrom, ToArrayHelper.toIntArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), (AllocationFunction.OfFloatArray) SegmentAllocator::allocateFrom, ToArrayHelper.toFloatArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), (AllocationFunction.OfLongArray) SegmentAllocator::allocateFrom, ToArrayHelper.toLongArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), (AllocationFunction.OfDoubleArray) SegmentAllocator::allocateFrom, ToArrayHelper.toDoubleArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfCharArray) SegmentAllocator::allocateFrom, ToArrayHelper.toCharArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfShortArray) SegmentAllocator::allocateFrom, ToArrayHelper.toShortArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfIntArray) SegmentAllocator::allocateFrom, ToArrayHelper.toIntArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfFloatArray) SegmentAllocator::allocateFrom, ToArrayHelper.toFloatArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfLongArray) SegmentAllocator::allocateFrom, ToArrayHelper.toLongArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfDoubleArray) SegmentAllocator::allocateFrom, ToArrayHelper.toDoubleArray }); }; return arrayAllocations.toArray(Object[][]::new); } interface AllocationFunction { MemorySegment allocate(SegmentAllocator allocator, L layout, X value); interface OfByte extends AllocationFunction { } interface OfBoolean extends AllocationFunction { } interface OfChar extends AllocationFunction { } interface OfShort extends AllocationFunction { } interface OfInt extends AllocationFunction { } interface OfFloat extends AllocationFunction { } interface OfLong extends AllocationFunction { } interface OfDouble extends AllocationFunction { } interface OfAddress extends AllocationFunction { } interface OfByteArray extends AllocationFunction { } interface OfCharArray extends AllocationFunction { } interface OfShortArray extends AllocationFunction { } interface OfIntArray extends AllocationFunction { } interface OfFloatArray extends AllocationFunction { } interface OfLongArray extends AllocationFunction { } interface OfDoubleArray extends AllocationFunction { } } enum AllocationFactory { SLICING(true, (size, arena) -> { return SegmentAllocator.slicingAllocator(arena.allocate(size, 1)); }); private final boolean isBound; private final BiFunction factory; AllocationFactory(boolean isBound, BiFunction factory) { this.isBound = isBound; this.factory = factory; } SegmentAllocator allocator(long size, Arena arena) { return factory.apply(size, arena); } public boolean isBound() { return isBound; } } interface ToArrayHelper { T array(); T toArray(MemorySegment segment, ValueLayout layout); ToArrayHelper toByteArray = new ToArrayHelper<>() { @Override public byte[] array() { return new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; } @Override public byte[] toArray(MemorySegment segment, ValueLayout layout) { ByteBuffer buffer = segment.asByteBuffer().order(layout.order()); byte[] found = new byte[buffer.limit()]; buffer.get(found); return found; } }; ToArrayHelper toCharArray = new ToArrayHelper<>() { @Override public char[] array() { return new char[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; } @Override public char[] toArray(MemorySegment segment, ValueLayout layout) { CharBuffer buffer = segment.asByteBuffer().order(layout.order()).asCharBuffer(); char[] found = new char[buffer.limit()]; buffer.get(found); return found; } }; ToArrayHelper toShortArray = new ToArrayHelper<>() { @Override public short[] array() { return new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; } @Override public short[] toArray(MemorySegment segment, ValueLayout layout) { ShortBuffer buffer = segment.asByteBuffer().order(layout.order()).asShortBuffer(); short[] found = new short[buffer.limit()]; buffer.get(found); return found; } }; ToArrayHelper toIntArray = new ToArrayHelper<>() { @Override public int[] array() { return new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; } @Override public int[] toArray(MemorySegment segment, ValueLayout layout) { IntBuffer buffer = segment.asByteBuffer().order(layout.order()).asIntBuffer(); int[] found = new int[buffer.limit()]; buffer.get(found); return found; } }; ToArrayHelper toFloatArray = new ToArrayHelper<>() { @Override public float[] array() { return new float[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; } @Override public float[] toArray(MemorySegment segment, ValueLayout layout) { FloatBuffer buffer = segment.asByteBuffer().order(layout.order()).asFloatBuffer(); float[] found = new float[buffer.limit()]; buffer.get(found); return found; } }; ToArrayHelper toLongArray = new ToArrayHelper<>() { @Override public long[] array() { return new long[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; } @Override public long[] toArray(MemorySegment segment, ValueLayout layout) { LongBuffer buffer = segment.asByteBuffer().order(layout.order()).asLongBuffer(); long[] found = new long[buffer.limit()]; buffer.get(found); return found; } }; ToArrayHelper toDoubleArray = new ToArrayHelper<>() { @Override public double[] array() { return new double[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; } @Override public double[] toArray(MemorySegment segment, ValueLayout layout) { DoubleBuffer buffer = segment.asByteBuffer().order(layout.order()).asDoubleBuffer(); double[] found = new double[buffer.limit()]; buffer.get(found); return found; } }; } @DataProvider(name = "allocators") static Object[][] allocators() { return new Object[][] { { SegmentAllocator.prefixAllocator(Arena.global().allocate(10, 1)) }, }; } }