1 /* 2 * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @modules java.base/sun.nio.ch java.base/jdk.internal.foreign 27 * @run testng/othervm/timeout=600 --enable-native-access=ALL-UNNAMED TestByteBuffer 28 */ 29 30 import java.lang.foreign.*; 31 import java.lang.foreign.MemoryLayout.PathElement; 32 33 import java.io.File; 34 import java.io.IOException; 35 import java.lang.invoke.MethodHandle; 36 import java.lang.invoke.MethodHandles; 37 import java.lang.invoke.VarHandle; 38 import java.lang.ref.Cleaner; 39 import java.lang.ref.Reference; 40 import java.lang.ref.WeakReference; 41 import java.lang.reflect.InvocationTargetException; 42 import java.lang.reflect.Method; 43 import java.lang.reflect.Modifier; 44 import java.net.URI; 45 import java.nio.Buffer; 46 import java.nio.ByteBuffer; 47 import java.nio.ByteOrder; 48 import java.nio.CharBuffer; 49 import java.nio.DoubleBuffer; 50 import java.nio.FloatBuffer; 51 import java.nio.IntBuffer; 52 import java.nio.LongBuffer; 53 import java.nio.MappedByteBuffer; 54 import java.nio.ShortBuffer; 55 import java.nio.channels.FileChannel; 56 import java.nio.file.Files; 57 import java.nio.file.Path; 58 import java.nio.file.StandardOpenOption; 59 import java.util.ArrayList; 60 import java.util.HashMap; 61 import java.util.List; 62 import java.util.Map; 63 import java.util.concurrent.atomic.AtomicBoolean; 64 import java.util.function.BiConsumer; 65 import java.util.function.BiFunction; 66 import java.util.function.Consumer; 67 import java.util.function.Function; 68 import java.util.function.Predicate; 69 import java.util.function.Supplier; 70 import java.util.stream.Stream; 71 72 import jdk.internal.foreign.HeapMemorySegmentImpl; 73 import jdk.internal.foreign.MappedMemorySegmentImpl; 74 import jdk.internal.foreign.NativeMemorySegmentImpl; 75 import org.testng.SkipException; 76 import org.testng.annotations.*; 77 import sun.nio.ch.DirectBuffer; 78 79 import static java.lang.foreign.ValueLayout.*; 80 import static org.testng.Assert.*; 81 82 public class TestByteBuffer { 83 84 static final Path tempPath; 85 86 static { 87 try { 88 File file = File.createTempFile("buffer", "txt"); 89 file.deleteOnExit(); 90 tempPath = file.toPath(); 91 Files.write(file.toPath(), new byte[256], StandardOpenOption.WRITE); 92 93 } catch (IOException ex) { 94 throw new ExceptionInInitializerError(ex); 95 } 96 } 97 98 static final ValueLayout.OfChar BB_CHAR = JAVA_CHAR_UNALIGNED.withOrder(ByteOrder.BIG_ENDIAN); 99 static final ValueLayout.OfShort BB_SHORT = JAVA_SHORT_UNALIGNED.withOrder(ByteOrder.BIG_ENDIAN); 100 static final ValueLayout.OfInt BB_INT = JAVA_INT_UNALIGNED.withOrder(ByteOrder.BIG_ENDIAN); 101 static final ValueLayout.OfLong BB_LONG = JAVA_LONG_UNALIGNED.withOrder(ByteOrder.BIG_ENDIAN); 102 static final ValueLayout.OfFloat BB_FLOAT = JAVA_FLOAT_UNALIGNED.withOrder(ByteOrder.BIG_ENDIAN); 103 static final ValueLayout.OfDouble BB_DOUBLE = JAVA_DOUBLE_UNALIGNED.withOrder(ByteOrder.BIG_ENDIAN); 104 105 static SequenceLayout tuples = MemoryLayout.sequenceLayout(500, 106 MemoryLayout.structLayout( 107 BB_INT.withName("index"), 108 BB_FLOAT.withName("value") 109 )); 110 111 static final SequenceLayout bytes = MemoryLayout.sequenceLayout(100, JAVA_BYTE); 112 static final SequenceLayout chars = MemoryLayout.sequenceLayout(100, BB_CHAR); 113 static final SequenceLayout shorts = MemoryLayout.sequenceLayout(100, BB_SHORT); 114 static final SequenceLayout ints = MemoryLayout.sequenceLayout(100, BB_INT); 115 static final SequenceLayout floats = MemoryLayout.sequenceLayout(100, BB_FLOAT); 116 static final SequenceLayout longs = MemoryLayout.sequenceLayout(100, BB_LONG); 117 static final SequenceLayout doubles = MemoryLayout.sequenceLayout(100, BB_DOUBLE); 118 119 static final VarHandle indexHandle = tuples.varHandle(PathElement.sequenceElement(), PathElement.groupElement("index")); 120 static final VarHandle valueHandle = tuples.varHandle(PathElement.sequenceElement(), PathElement.groupElement("value")); 121 122 static void initTuples(MemorySegment base, long count) { 123 for (long i = 0; i < count ; i++) { 124 indexHandle.set(base, 0L, i, (int)i); 125 valueHandle.set(base, 0L, i, (float)(i / 500f)); 126 } 127 } 128 129 static void checkTuples(MemorySegment base, ByteBuffer bb, long count) { 130 for (long i = 0; i < count ; i++) { 131 int index; 132 float value; 133 assertEquals(index = bb.getInt(), (int)indexHandle.get(base, 0L, i)); 134 assertEquals(value = bb.getFloat(), (float)valueHandle.get(base, 0L, i)); 135 assertEquals(value, index / 500f); 136 } 137 } 138 139 static void initBytes(MemorySegment base, SequenceLayout seq, BiConsumer<MemorySegment, Long> handleSetter) { 140 for (long i = 0; i < seq.elementCount() ; i++) { 141 handleSetter.accept(base, i); 142 } 143 } 144 145 static <Z extends Buffer> void checkBytes(MemorySegment base, SequenceLayout layout, 146 Function<ByteBuffer, Z> bufFactory, 147 BiFunction<MemorySegment, Long, Object> handleExtractor, 148 Function<Z, Object> bufferExtractor) { 149 long nelems = layout.elementCount(); 150 long elemSize = layout.elementLayout().byteSize(); 151 for (long i = 0 ; i < nelems ; i++) { 152 long limit = nelems - i; 153 MemorySegment resizedSegment = base.asSlice(i * elemSize, limit * elemSize); 154 ByteBuffer bb = resizedSegment.asByteBuffer(); 155 Z z = bufFactory.apply(bb); 156 MemorySegment segmentBufferView = MemorySegment.ofBuffer(z); 157 for (long j = i ; j < limit ; j++) { 158 Object handleValue = handleExtractor.apply(resizedSegment, j - i); 159 Object bufferValue = bufferExtractor.apply(z); 160 Object handleViewValue = handleExtractor.apply(segmentBufferView, j - i); 161 if (handleValue instanceof Number) { 162 assertEquals(((Number)handleValue).longValue(), j); 163 assertEquals(((Number)bufferValue).longValue(), j); 164 assertEquals(((Number)handleViewValue).longValue(), j); 165 } else { 166 assertEquals((long)(char)handleValue, j); 167 assertEquals((long)(char)bufferValue, j); 168 assertEquals((long)(char)handleViewValue, j); 169 } 170 } 171 } 172 } 173 174 @Test 175 public void testOffheap() { 176 try (Arena arena = Arena.ofConfined()) { 177 MemorySegment segment = arena.allocate(tuples);; 178 initTuples(segment, tuples.elementCount()); 179 180 ByteBuffer bb = segment.asByteBuffer(); 181 checkTuples(segment, bb, tuples.elementCount()); 182 } 183 } 184 185 @Test 186 public void testHeap() { 187 byte[] arr = new byte[(int) tuples.byteSize()]; 188 MemorySegment region = MemorySegment.ofArray(arr); 189 initTuples(region, tuples.elementCount()); 190 191 ByteBuffer bb = region.asByteBuffer(); 192 checkTuples(region, bb, tuples.elementCount()); 193 } 194 195 @Test 196 public void testChannel() throws Throwable { 197 File f = new File("test.out"); 198 assertTrue(f.createNewFile()); 199 f.deleteOnExit(); 200 201 //write to channel 202 try (FileChannel channel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { 203 withMappedBuffer(channel, FileChannel.MapMode.READ_WRITE, 0, tuples.byteSize(), mbb -> { 204 MemorySegment segment = MemorySegment.ofBuffer(mbb); 205 initTuples(segment, tuples.elementCount()); 206 mbb.force(); 207 }); 208 } 209 210 //read from channel 211 try (FileChannel channel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) { 212 withMappedBuffer(channel, FileChannel.MapMode.READ_ONLY, 0, tuples.byteSize(), mbb -> { 213 MemorySegment segment = MemorySegment.ofBuffer(mbb); 214 checkTuples(segment, mbb, tuples.elementCount()); 215 }); 216 } 217 } 218 219 @Test 220 public void testDefaultAccessModesMappedSegment() throws Throwable { 221 try (Arena arena = Arena.ofConfined(); 222 FileChannel fileChannel = FileChannel.open(tempPath, StandardOpenOption.READ, StandardOpenOption.WRITE)) { 223 MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 8L, arena); 224 assertFalse(segment.isReadOnly()); 225 } 226 227 try (Arena arena = Arena.ofConfined(); 228 FileChannel fileChannel = FileChannel.open(tempPath, StandardOpenOption.READ)) { 229 MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, 8L, arena); 230 assertTrue(segment.isReadOnly()); 231 } 232 } 233 234 @Test 235 public void testMappedSegment() throws Throwable { 236 File f = new File("test2.out"); 237 f.createNewFile(); 238 f.deleteOnExit(); 239 240 try (Arena arena = Arena.ofConfined(); 241 FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { 242 //write to channel 243 MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, tuples.byteSize(), arena); 244 initTuples(segment, tuples.elementCount()); 245 segment.force(); 246 } 247 248 try (Arena arena = Arena.ofConfined(); 249 FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) { 250 //read from channel 251 MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, tuples.byteSize(), arena); 252 checkTuples(segment, segment.asByteBuffer(), tuples.elementCount()); 253 } 254 } 255 256 @Test(dataProvider = "mappedOps", expectedExceptions = IllegalStateException.class) 257 public void testMappedSegmentOperations(MappedSegmentOp mappedBufferOp) throws Throwable { 258 File f = new File("test3.out"); 259 f.createNewFile(); 260 f.deleteOnExit(); 261 262 Arena arena = Arena.ofConfined(); 263 try (FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { 264 MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 8L, arena); 265 assertTrue(segment.isMapped()); 266 arena.close(); 267 mappedBufferOp.apply(segment); 268 } 269 } 270 271 @Test 272 public void testMappedSegmentOffset() throws Throwable { 273 File f = new File("test3.out"); 274 f.createNewFile(); 275 f.deleteOnExit(); 276 277 MemoryLayout tupleLayout = tuples.elementLayout(); 278 279 // write one at a time 280 for (int i = 0 ; i < tuples.byteSize() ; i += tupleLayout.byteSize()) { 281 try (Arena arena = Arena.ofConfined(); 282 FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { 283 //write to channel 284 MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, i, tuples.byteSize(), arena); 285 initTuples(segment, 1); 286 segment.force(); 287 } 288 } 289 290 // check one at a time 291 for (int i = 0 ; i < tuples.byteSize() ; i += tupleLayout.byteSize()) { 292 try (Arena arena = Arena.ofConfined(); 293 FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) { 294 //read from channel 295 MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, tuples.byteSize(), arena); 296 checkTuples(segment, segment.asByteBuffer(), 1); 297 } 298 } 299 } 300 301 @Test(dataProvider = "fromArrays") 302 public void testAsByteBufferFromNonByteArray(MemorySegment segment) { 303 if (!segment.heapBase().map(a -> a instanceof byte[]).get()) { 304 // This should not work as the segment is not backed by a byte array 305 assertThrows(UnsupportedOperationException.class, segment::asByteBuffer); 306 } 307 } 308 309 @Test 310 public void testMappedSegmentAsByteBuffer() throws Throwable { 311 File f = new File("test4.out"); 312 assertTrue(f.createNewFile()); 313 f.deleteOnExit(); 314 315 for (var mapOption : List.of(FileChannel.MapMode.READ_WRITE, FileChannel.MapMode.READ_ONLY, FileChannel.MapMode.PRIVATE)) { 316 for (var arena : List.of(Arena.ofConfined(), Arena.global())) { 317 try (FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { 318 //write to channel 319 MemorySegment segment = fileChannel.map(mapOption, 0L, 32L, arena); 320 segment.force(); 321 segment.load(); 322 segment.isLoaded(); 323 segment.unload(); 324 ByteBuffer byteBuffer = segment.asByteBuffer(); 325 assertEquals(byteBuffer.capacity(), segment.byteSize()); 326 assertEquals(byteBuffer.isReadOnly(), segment.isReadOnly()); 327 assertTrue(byteBuffer.isDirect()); 328 } catch (IOException e) { 329 if (e.getMessage().equals("Function not implemented")) 330 throw new SkipException(e.getMessage(), e); 331 } finally { 332 if (arena.scope() != Arena.global().scope()) { 333 arena.close(); 334 } 335 } 336 } 337 } 338 } 339 340 static final long LARGE_SIZE = (2L * 1024L + 512L) * 1024L * 1024L; // 2.5 GiB 341 342 @Test 343 public void testLargeMappedSegment() throws Throwable { 344 if (System.getProperty("sun.arch.data.model").equals("32")) { 345 throw new SkipException("large mapped files not supported on 32-bit systems"); 346 } 347 348 File f = new File("testLargeMappedSegment.out"); 349 f.createNewFile(); 350 f.deleteOnExit(); 351 352 try (Arena arena = Arena.ofConfined(); 353 FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { 354 MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, LARGE_SIZE, arena); 355 segment.isLoaded(); 356 segment.load(); 357 segment.isLoaded(); 358 segment.force(); 359 segment.isLoaded(); 360 segment.unload(); 361 segment.isLoaded(); 362 } catch(IOException e) { 363 if (e.getMessage().equals("Function not implemented")) 364 throw new SkipException(e.getMessage(), e); 365 } 366 } 367 368 static void withMappedBuffer(FileChannel channel, FileChannel.MapMode mode, long pos, long size, Consumer<MappedByteBuffer> action) throws Throwable { 369 MappedByteBuffer mbb = channel.map(mode, pos, size); 370 var ref = new WeakReference<>(mbb); 371 action.accept(mbb); 372 mbb = null; 373 //wait for it to be GCed 374 System.gc(); 375 while (ref.get() != null) { 376 Thread.sleep(20); 377 } 378 } 379 380 static void checkByteArrayAlignment(MemoryLayout layout) { 381 if (layout.byteSize() > 4 382 && System.getProperty("sun.arch.data.model").equals("32")) { 383 throw new SkipException("avoid unaligned access on 32-bit system"); 384 } 385 } 386 387 @Test(dataProvider = "bufferOps") 388 public void testScopedBuffer(Function<ByteBuffer, Buffer> bufferFactory, @NoInjection Method method, Object[] args) { 389 Buffer bb; 390 try (Arena arena = Arena.ofConfined()) { 391 MemorySegment segment = arena.allocate(bytes);; 392 bb = bufferFactory.apply(segment.asByteBuffer()); 393 } 394 //outside of session!! 395 try { 396 method.invoke(bb, args); 397 fail("Exception expected"); 398 } catch (InvocationTargetException ex) { 399 Throwable cause = ex.getCause(); 400 if (cause instanceof IllegalStateException) { 401 //all get/set buffer operation should fail because of the session check 402 assertTrue(ex.getCause().getMessage().contains("Already closed")); 403 } else { 404 //all other exceptions were unexpected - fail 405 fail("Unexpected exception", cause); 406 } 407 } catch (Throwable ex) { 408 //unexpected exception - fail 409 fail("Unexpected exception", ex); 410 } 411 } 412 413 @Test(dataProvider = "bufferHandleOps") 414 public void testScopedBufferAndVarHandle(VarHandle bufferHandle) { 415 ByteBuffer bb; 416 try (Arena arena = Arena.ofConfined()) { 417 MemorySegment segment = arena.allocate(bytes);; 418 bb = segment.asByteBuffer(); 419 for (Map.Entry<MethodHandle, Object[]> e : varHandleMembers(bb, bufferHandle).entrySet()) { 420 MethodHandle handle = e.getKey().bindTo(bufferHandle) 421 .asSpreader(Object[].class, e.getValue().length); 422 try { 423 handle.invoke(e.getValue()); 424 } catch (UnsupportedOperationException ex) { 425 //skip 426 } catch (Throwable ex) { 427 //should not fail - segment is alive! 428 fail(); 429 } 430 } 431 } 432 for (Map.Entry<MethodHandle, Object[]> e : varHandleMembers(bb, bufferHandle).entrySet()) { 433 try { 434 MethodHandle handle = e.getKey().bindTo(bufferHandle) 435 .asSpreader(Object[].class, e.getValue().length); 436 handle.invoke(e.getValue()); 437 fail(); 438 } catch (IllegalStateException ex) { 439 assertTrue(ex.getMessage().contains("Already closed")); 440 } catch (UnsupportedOperationException ex) { 441 //skip 442 } catch (Throwable ex) { 443 fail(); 444 } 445 } 446 } 447 448 @Test(dataProvider = "bufferOps") 449 public void testDirectBuffer(Function<ByteBuffer, Buffer> bufferFactory, @NoInjection Method method, Object[] args) { 450 try (Arena arena = Arena.ofConfined()) { 451 MemorySegment segment = arena.allocate(bytes);; 452 Buffer bb = bufferFactory.apply(segment.asByteBuffer()); 453 assertTrue(bb.isDirect()); 454 DirectBuffer directBuffer = ((DirectBuffer)bb); 455 assertEquals(directBuffer.address(), segment.address()); 456 assertTrue((directBuffer.attachment() == null) == (bb instanceof ByteBuffer)); 457 assertTrue(directBuffer.cleaner() == null); 458 } 459 } 460 461 @Test(dataProvider="resizeOps") 462 public void testResizeOffheap(Consumer<MemorySegment> checker, Consumer<MemorySegment> initializer, SequenceLayout seq) { 463 try (Arena arena = Arena.ofConfined()) { 464 MemorySegment segment = arena.allocate(seq);; 465 initializer.accept(segment); 466 checker.accept(segment); 467 } 468 } 469 470 @Test(dataProvider="resizeOps") 471 public void testResizeHeap(Consumer<MemorySegment> checker, Consumer<MemorySegment> initializer, SequenceLayout seq) { 472 checkByteArrayAlignment(seq.elementLayout()); 473 int capacity = (int)seq.byteSize(); 474 MemorySegment base = MemorySegment.ofArray(new byte[capacity]); 475 initializer.accept(base); 476 checker.accept(base); 477 } 478 479 @Test(dataProvider="resizeOps") 480 public void testResizeBuffer(Consumer<MemorySegment> checker, Consumer<MemorySegment> initializer, SequenceLayout seq) { 481 checkByteArrayAlignment(seq.elementLayout()); 482 int capacity = (int)seq.byteSize(); 483 MemorySegment base = MemorySegment.ofBuffer(ByteBuffer.wrap(new byte[capacity])); 484 initializer.accept(base); 485 checker.accept(base); 486 } 487 488 @Test(dataProvider="resizeOps") 489 public void testResizeRoundtripHeap(Consumer<MemorySegment> checker, Consumer<MemorySegment> initializer, SequenceLayout seq) { 490 checkByteArrayAlignment(seq.elementLayout()); 491 int capacity = (int)seq.byteSize(); 492 byte[] arr = new byte[capacity]; 493 MemorySegment segment = MemorySegment.ofArray(arr); 494 initializer.accept(segment); 495 MemorySegment second = MemorySegment.ofBuffer(segment.asByteBuffer()); 496 checker.accept(second); 497 } 498 499 @Test(dataProvider="resizeOps") 500 public void testResizeRoundtripNative(Consumer<MemorySegment> checker, Consumer<MemorySegment> initializer, SequenceLayout seq) { 501 try (Arena arena = Arena.ofConfined()) { 502 MemorySegment segment = arena.allocate(seq);; 503 initializer.accept(segment); 504 MemorySegment second = MemorySegment.ofBuffer(segment.asByteBuffer()); 505 checker.accept(second); 506 } 507 } 508 509 @Test(expectedExceptions = IllegalStateException.class) 510 public void testBufferOnClosedSession() { 511 MemorySegment leaked; 512 try (Arena arena = Arena.ofConfined()) { 513 leaked = arena.allocate(bytes);; 514 } 515 ByteBuffer byteBuffer = leaked.asByteBuffer(); // ok 516 byteBuffer.get(); // should throw 517 } 518 519 @Test(expectedExceptions = IllegalStateException.class) 520 public void testTooBigForByteBuffer() { 521 MemorySegment segment = MemorySegment.NULL.reinterpret(Integer.MAX_VALUE + 10L); 522 segment.asByteBuffer(); 523 } 524 525 @Test(expectedExceptions = IllegalArgumentException.class) 526 public void testBadMapNegativeSize() throws IOException { 527 File f = new File("testNeg1.out"); 528 f.createNewFile(); 529 f.deleteOnExit(); 530 try (FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { 531 fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, -1L, Arena.ofAuto()); 532 } 533 } 534 535 @Test(expectedExceptions = IllegalArgumentException.class) 536 public void testBadMapNegativeOffset() throws IOException { 537 File f = new File("testNeg2.out"); 538 f.createNewFile(); 539 f.deleteOnExit(); 540 try (FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { 541 fileChannel.map(FileChannel.MapMode.READ_WRITE, -1L, 1L, Arena.ofAuto()); 542 } 543 } 544 545 @Test 546 public void testMapOffset() throws IOException { 547 File f = new File("testMapOffset.out"); 548 f.createNewFile(); 549 f.deleteOnExit(); 550 551 int SIZE = Byte.MAX_VALUE; 552 553 try (Arena arena = Arena.ofConfined(); 554 FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { 555 MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, SIZE, arena); 556 for (byte offset = 0; offset < SIZE; offset++) { 557 segment.set(JAVA_BYTE, offset, offset); 558 } 559 segment.force(); 560 } 561 562 for (int offset = 0 ; offset < SIZE ; offset++) { 563 try (Arena arena = Arena.ofConfined(); 564 FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) { 565 MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, offset, SIZE - offset, arena); 566 assertEquals(segment.get(JAVA_BYTE, 0), offset); 567 } 568 } 569 } 570 571 @Test 572 public void testMapZeroSize() throws IOException { 573 File f = new File("testPos1.out"); 574 f.createNewFile(); 575 f.deleteOnExit(); 576 //RW 577 try (Arena arena = Arena.ofConfined(); 578 FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { 579 MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 0L, arena); 580 assertEquals(segment.byteSize(), 0); 581 assertEquals(segment.isMapped(), true); 582 assertFalse(segment.isReadOnly()); 583 segment.force(); 584 segment.load(); 585 segment.isLoaded(); 586 segment.unload(); 587 ByteBuffer byteBuffer = segment.asByteBuffer(); 588 assertEquals(byteBuffer.capacity(), 0); 589 assertFalse(byteBuffer.isReadOnly()); 590 } 591 //RO 592 try (Arena arena = Arena.ofConfined(); 593 FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) { 594 MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, 0L, arena); 595 assertEquals(segment.byteSize(), 0); 596 assertEquals(segment.isMapped(), true); 597 assertTrue(segment.isReadOnly()); 598 segment.force(); 599 segment.load(); 600 segment.isLoaded(); 601 segment.unload(); 602 ByteBuffer byteBuffer = segment.asByteBuffer(); 603 assertEquals(byteBuffer.capacity(), 0); 604 assertTrue(byteBuffer.isReadOnly()); 605 } 606 } 607 608 @Test(expectedExceptions = UnsupportedOperationException.class) 609 public void testMapCustomPath() throws IOException { 610 Path path = Path.of(URI.create("jrt:/")); 611 try (FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ, StandardOpenOption.WRITE)) { 612 fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 0L, Arena.ofAuto()); 613 } 614 } 615 616 @Test(dataProvider="resizeOps") 617 public void testCopyHeapToNative(Consumer<MemorySegment> checker, Consumer<MemorySegment> initializer, SequenceLayout seq) { 618 checkByteArrayAlignment(seq.elementLayout()); 619 int bytes = (int)seq.byteSize(); 620 try (Arena arena = Arena.ofConfined()) { 621 MemorySegment nativeArray = arena.allocate(bytes, 1);; 622 MemorySegment heapArray = MemorySegment.ofArray(new byte[bytes]); 623 initializer.accept(heapArray); 624 nativeArray.copyFrom(heapArray); 625 checker.accept(nativeArray); 626 } 627 } 628 629 @Test(dataProvider="resizeOps") 630 public void testCopyNativeToHeap(Consumer<MemorySegment> checker, Consumer<MemorySegment> initializer, SequenceLayout seq) { 631 checkByteArrayAlignment(seq.elementLayout()); 632 int bytes = (int)seq.byteSize(); 633 try (Arena arena = Arena.ofConfined()) { 634 MemorySegment nativeArray = arena.allocate(seq);; 635 MemorySegment heapArray = MemorySegment.ofArray(new byte[bytes]); 636 initializer.accept(nativeArray); 637 heapArray.copyFrom(nativeArray); 638 checker.accept(heapArray); 639 } 640 } 641 642 @Test 643 public void testDefaultAccessModesOfBuffer() { 644 ByteBuffer rwBuffer = ByteBuffer.wrap(new byte[4]); 645 { 646 MemorySegment segment = MemorySegment.ofBuffer(rwBuffer); 647 assertFalse(segment.isReadOnly()); 648 } 649 650 { 651 ByteBuffer roBuffer = rwBuffer.asReadOnlyBuffer(); 652 MemorySegment segment = MemorySegment.ofBuffer(roBuffer); 653 assertTrue(segment.isReadOnly()); 654 } 655 } 656 657 @Test 658 public void testOfBufferScopeReachable() throws InterruptedException { 659 ByteBuffer buffer = ByteBuffer.allocateDirect(1000); 660 MemorySegment segment = MemorySegment.ofBuffer(buffer); 661 try { 662 AtomicBoolean reachable = new AtomicBoolean(true); 663 Cleaner.create().register(buffer, () -> { 664 reachable.set(false); 665 }); 666 buffer = null; 667 System.gc(); 668 // let's sleep to let cleaner run 669 Thread.sleep(100); 670 segment.get(JAVA_BYTE, 0); 671 if (!reachable.get()) { 672 throw new IllegalStateException(); 673 } 674 } finally { 675 Reference.reachabilityFence(segment); 676 } 677 } 678 679 @Test(dataProvider="bufferSources") 680 public void testBufferToSegment(ByteBuffer bb, Predicate<MemorySegment> segmentChecker) { 681 MemorySegment segment = MemorySegment.ofBuffer(bb); 682 assertEquals(segment.isReadOnly(), bb.isReadOnly()); 683 assertTrue(segmentChecker.test(segment)); 684 assertTrue(segmentChecker.test(segment.asSlice(0, segment.byteSize()))); 685 assertEquals(bb.capacity(), segment.byteSize()); 686 //another round trip 687 segment = MemorySegment.ofBuffer(segment.asByteBuffer()); 688 assertEquals(segment.isReadOnly(), bb.isReadOnly()); 689 assertTrue(segmentChecker.test(segment)); 690 assertTrue(segmentChecker.test(segment.asSlice(0, segment.byteSize()))); 691 assertEquals(bb.capacity(), segment.byteSize()); 692 } 693 694 @Test(dataProvider="bufferSources") 695 public void bufferProperties(ByteBuffer bb, Predicate<MemorySegment> _unused) { 696 MemorySegment segment = MemorySegment.ofBuffer(bb); 697 ByteBuffer buffer = segment.asByteBuffer(); 698 assertEquals(buffer.position(), 0); 699 assertEquals(buffer.capacity(), segment.byteSize()); 700 assertEquals(buffer.limit(), segment.byteSize()); 701 } 702 703 @Test 704 public void testRoundTripAccess() { 705 try (Arena arena = Arena.ofConfined()) { 706 MemorySegment ms = arena.allocate(4, 1);; 707 MemorySegment msNoAccess = ms.asReadOnly(); 708 MemorySegment msRoundTrip = MemorySegment.ofBuffer(msNoAccess.asByteBuffer()); 709 assertEquals(msRoundTrip.scope(), ms.scope()); 710 assertEquals(msNoAccess.isReadOnly(), msRoundTrip.isReadOnly()); 711 } 712 } 713 714 @Test(dataProvider = "bufferFactories") 715 public void testDerivedBufferScopes(Supplier<Buffer> bufferFactory) { 716 MemorySegment segment = MemorySegment.ofBuffer(bufferFactory.get()); 717 assertEquals(segment.scope(), segment.scope()); 718 // one level 719 assertEquals(segment.asSlice(0).scope(), segment.scope()); 720 assertEquals(segment.asReadOnly().scope(), segment.scope()); 721 // two levels 722 assertEquals(segment.asSlice(0).asReadOnly().scope(), segment.scope()); 723 assertEquals(segment.asReadOnly().asSlice(0).scope(), segment.scope()); 724 // check fresh every time 725 MemorySegment another = MemorySegment.ofBuffer(bufferFactory.get()); 726 assertNotEquals(segment.scope(), another.scope()); 727 } 728 729 @Test(expectedExceptions = IllegalStateException.class) 730 public void testDeadAccessOnClosedBufferSegment() { 731 Arena arena = Arena.ofConfined(); 732 MemorySegment s1 = arena.allocate(JAVA_INT); 733 MemorySegment s2 = MemorySegment.ofBuffer(s1.asByteBuffer()); 734 735 // memory freed 736 arena.close(); 737 738 s2.set(JAVA_INT, 0, 10); // Dead access! 739 } 740 741 @Test(dataProvider = "closeableArenas") 742 public void closeableArenas(Supplier<Arena> arenaSupplier) throws IOException { 743 File tmp = File.createTempFile("tmp", "txt"); 744 tmp.deleteOnExit(); 745 try (FileChannel channel = FileChannel.open(tmp.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE) ; 746 Arena arena = arenaSupplier.get()) { 747 MemorySegment segment = arena.allocate(10, 1);; 748 for (int i = 0; i < 10; i++) { 749 segment.set(JAVA_BYTE, i, (byte) i); 750 } 751 ByteBuffer bb = segment.asByteBuffer(); 752 assertEquals(channel.write(bb), 10); 753 segment.fill((byte)0x00); 754 assertEquals(bb.clear(), ByteBuffer.wrap(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); 755 assertEquals(channel.position(0).read(bb.clear()), 10); 756 assertEquals(bb.flip(), ByteBuffer.wrap(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); 757 } 758 } 759 760 static final Class<IllegalStateException> ISE = IllegalStateException.class; 761 762 @Test(dataProvider = "closeableArenas") 763 public void testIOOnClosedSegmentBuffer(Supplier<Arena> arenaSupplier) throws IOException { 764 File tmp = File.createTempFile("tmp", "txt"); 765 tmp.deleteOnExit(); 766 Arena arena = arenaSupplier.get(); 767 try (FileChannel channel = FileChannel.open(tmp.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { 768 MemorySegment segment = arena.allocate(10, 1); 769 for (int i = 0; i < 10; i++) { 770 segment.set(JAVA_BYTE, i, (byte) i); 771 } 772 ByteBuffer bb = segment.asByteBuffer(); 773 arena.close(); 774 assertThrows(ISE, () -> channel.read(bb)); 775 assertThrows(ISE, () -> channel.read(new ByteBuffer[] {bb})); 776 assertThrows(ISE, () -> channel.read(new ByteBuffer[] {bb}, 0, 1)); 777 assertThrows(ISE, () -> channel.write(bb)); 778 assertThrows(ISE, () -> channel.write(new ByteBuffer[] {bb})); 779 assertThrows(ISE, () -> channel.write(new ByteBuffer[] {bb}, 0 ,1)); 780 } 781 } 782 783 @Test 784 public void buffersAndArraysFromSlices() { 785 try (Arena arena = Arena.ofShared()) { 786 MemorySegment segment = arena.allocate(16, 1);; 787 int newSize = 8; 788 var slice = segment.asSlice(4, newSize); 789 790 var bytes = slice.toArray(JAVA_BYTE); 791 assertEquals(newSize, bytes.length); 792 793 var buffer = slice.asByteBuffer(); 794 // Fails for heap segments, but passes for native segments: 795 assertEquals(0, buffer.position()); 796 assertEquals(newSize, buffer.limit()); 797 assertEquals(newSize, buffer.capacity()); 798 } 799 } 800 801 @Test 802 public void viewsFromSharedSegment() { 803 try (Arena arena = Arena.ofShared()) { 804 MemorySegment segment = arena.allocate(16, 1);; 805 var byteBuffer = segment.asByteBuffer(); 806 byteBuffer.asReadOnlyBuffer(); 807 byteBuffer.slice(0, 8); 808 } 809 } 810 811 @DataProvider(name = "segments") 812 public static Object[][] segments() throws Throwable { 813 return new Object[][] { 814 { (Supplier<MemorySegment>) () -> Arena.ofAuto().allocate(16, 1)}, 815 { (Supplier<MemorySegment>) () -> Arena.ofConfined().allocate(16, 1)}, 816 { (Supplier<MemorySegment>) () -> MemorySegment.ofArray(new byte[16]) } 817 }; 818 } 819 820 @DataProvider(name = "closeableArenas") 821 public static Object[][] closeableArenas() { 822 return new Object[][] { 823 { (Supplier<Arena>) Arena::ofConfined}, 824 { (Supplier<Arena>) Arena::ofShared}, 825 }; 826 } 827 828 @DataProvider(name = "bufferOps") 829 public static Object[][] bufferOps() throws Throwable { 830 List<Object[]> args = new ArrayList<>(); 831 bufferOpsArgs(args, bb -> bb, ByteBuffer.class); 832 bufferOpsArgs(args, ByteBuffer::asCharBuffer, CharBuffer.class); 833 bufferOpsArgs(args, ByteBuffer::asShortBuffer, ShortBuffer.class); 834 bufferOpsArgs(args, ByteBuffer::asIntBuffer, IntBuffer.class); 835 bufferOpsArgs(args, ByteBuffer::asFloatBuffer, FloatBuffer.class); 836 bufferOpsArgs(args, ByteBuffer::asLongBuffer, LongBuffer.class); 837 bufferOpsArgs(args, ByteBuffer::asDoubleBuffer, DoubleBuffer.class); 838 return args.toArray(Object[][]::new); 839 } 840 841 static void bufferOpsArgs(List<Object[]> argsList, Function<ByteBuffer, Buffer> factory, Class<?> bufferClass) { 842 for (Method m : bufferClass.getMethods()) { 843 //skip statics and method declared in j.l.Object 844 if (m.getDeclaringClass().equals(Object.class) 845 || ((m.getModifiers() & Modifier.STATIC) != 0) 846 || (!m.getName().contains("get") && !m.getName().contains("put")) 847 || m.getParameterCount() > 2) continue; 848 Object[] args = Stream.of(m.getParameterTypes()) 849 .map(TestByteBuffer::defaultValue) 850 .toArray(); 851 argsList.add(new Object[] { factory, m, args }); 852 } 853 } 854 855 @DataProvider(name = "bufferHandleOps") 856 public static Object[][] bufferHandleOps() throws Throwable { 857 return new Object[][]{ 858 { MethodHandles.byteBufferViewVarHandle(char[].class, ByteOrder.nativeOrder()) }, 859 { MethodHandles.byteBufferViewVarHandle(short[].class, ByteOrder.nativeOrder()) }, 860 { MethodHandles.byteBufferViewVarHandle(int[].class, ByteOrder.nativeOrder()) }, 861 { MethodHandles.byteBufferViewVarHandle(long[].class, ByteOrder.nativeOrder()) }, 862 { MethodHandles.byteBufferViewVarHandle(float[].class, ByteOrder.nativeOrder()) }, 863 { MethodHandles.byteBufferViewVarHandle(double[].class, ByteOrder.nativeOrder()) } 864 }; 865 } 866 867 static Map<MethodHandle, Object[]> varHandleMembers(ByteBuffer bb, VarHandle handle) { 868 Map<MethodHandle, Object[]> members = new HashMap<>(); 869 for (VarHandle.AccessMode mode : VarHandle.AccessMode.values()) { 870 Class<?>[] params = handle.accessModeType(mode).parameterArray(); 871 Object[] args = Stream.concat(Stream.of(bb), Stream.of(params).skip(1) 872 .map(TestByteBuffer::defaultValue)) 873 .toArray(); 874 try { 875 members.put(MethodHandles.varHandleInvoker(mode, handle.accessModeType(mode)), args); 876 } catch (Throwable ex) { 877 throw new AssertionError(ex); 878 } 879 } 880 return members; 881 } 882 883 @DataProvider(name = "resizeOps") 884 public Object[][] resizeOps() { 885 Consumer<MemorySegment> byteInitializer = 886 (base) -> initBytes(base, bytes, (addr, pos) -> addr.set(JAVA_BYTE, pos, (byte)(long)pos)); 887 Consumer<MemorySegment> charInitializer = 888 (base) -> initBytes(base, chars, (addr, pos) -> addr.setAtIndex(BB_CHAR, pos, (char)(long)pos)); 889 Consumer<MemorySegment> shortInitializer = 890 (base) -> initBytes(base, shorts, (addr, pos) -> addr.setAtIndex(BB_SHORT, pos, (short)(long)pos)); 891 Consumer<MemorySegment> intInitializer = 892 (base) -> initBytes(base, ints, (addr, pos) -> addr.setAtIndex(BB_INT, pos, (int)(long)pos)); 893 Consumer<MemorySegment> floatInitializer = 894 (base) -> initBytes(base, floats, (addr, pos) -> addr.setAtIndex(BB_FLOAT, pos, (float)(long)pos)); 895 Consumer<MemorySegment> longInitializer = 896 (base) -> initBytes(base, longs, (addr, pos) -> addr.setAtIndex(BB_LONG, pos, (long)pos)); 897 Consumer<MemorySegment> doubleInitializer = 898 (base) -> initBytes(base, doubles, (addr, pos) -> addr.setAtIndex(BB_DOUBLE, pos, (double)(long)pos)); 899 900 Consumer<MemorySegment> byteChecker = 901 (base) -> checkBytes(base, bytes, Function.identity(), (addr, pos) -> addr.get(JAVA_BYTE, pos), ByteBuffer::get); 902 Consumer<MemorySegment> charChecker = 903 (base) -> checkBytes(base, chars, ByteBuffer::asCharBuffer, (addr, pos) -> addr.getAtIndex(BB_CHAR, pos), CharBuffer::get); 904 Consumer<MemorySegment> shortChecker = 905 (base) -> checkBytes(base, shorts, ByteBuffer::asShortBuffer, (addr, pos) -> addr.getAtIndex(BB_SHORT, pos), ShortBuffer::get); 906 Consumer<MemorySegment> intChecker = 907 (base) -> checkBytes(base, ints, ByteBuffer::asIntBuffer, (addr, pos) -> addr.getAtIndex(BB_INT, pos), IntBuffer::get); 908 Consumer<MemorySegment> floatChecker = 909 (base) -> checkBytes(base, floats, ByteBuffer::asFloatBuffer, (addr, pos) -> addr.getAtIndex(BB_FLOAT, pos), FloatBuffer::get); 910 Consumer<MemorySegment> longChecker = 911 (base) -> checkBytes(base, longs, ByteBuffer::asLongBuffer, (addr, pos) -> addr.getAtIndex(BB_LONG, pos), LongBuffer::get); 912 Consumer<MemorySegment> doubleChecker = 913 (base) -> checkBytes(base, doubles, ByteBuffer::asDoubleBuffer, (addr, pos) -> addr.getAtIndex(BB_DOUBLE, pos), DoubleBuffer::get); 914 915 return new Object[][]{ 916 {byteChecker, byteInitializer, bytes}, 917 {charChecker, charInitializer, chars}, 918 {shortChecker, shortInitializer, shorts}, 919 {intChecker, intInitializer, ints}, 920 {floatChecker, floatInitializer, floats}, 921 {longChecker, longInitializer, longs}, 922 {doubleChecker, doubleInitializer, doubles} 923 }; 924 } 925 926 static Object defaultValue(Class<?> c) { 927 if (c.isPrimitive()) { 928 if (c == char.class) { 929 return (char)0; 930 } else if (c == boolean.class) { 931 return false; 932 } else if (c == byte.class) { 933 return (byte)0; 934 } else if (c == short.class) { 935 return (short)0; 936 } else if (c == int.class) { 937 return 0; 938 } else if (c == long.class) { 939 return 0L; 940 } else if (c == float.class) { 941 return 0f; 942 } else if (c == double.class) { 943 return 0d; 944 } else { 945 throw new IllegalStateException(); 946 } 947 } else if (c.isArray()) { 948 if (c == char[].class) { 949 return new char[1]; 950 } else if (c == boolean[].class) { 951 return new boolean[1]; 952 } else if (c == byte[].class) { 953 return new byte[1]; 954 } else if (c == short[].class) { 955 return new short[1]; 956 } else if (c == int[].class) { 957 return new int[1]; 958 } else if (c == long[].class) { 959 return new long[1]; 960 } else if (c == float[].class) { 961 return new float[1]; 962 } else if (c == double[].class) { 963 return new double[1]; 964 } else { 965 throw new IllegalStateException(); 966 } 967 } else if (c == String.class) { 968 return "asdf"; 969 } else if (c == ByteBuffer.class) { 970 return ByteBuffer.wrap(new byte[1]); 971 } else if (c == CharBuffer.class) { 972 return CharBuffer.wrap(new char[1]); 973 } else if (c == ShortBuffer.class) { 974 return ShortBuffer.wrap(new short[1]); 975 } else if (c == IntBuffer.class) { 976 return IntBuffer.wrap(new int[1]); 977 } else if (c == FloatBuffer.class) { 978 return FloatBuffer.wrap(new float[1]); 979 } else if (c == LongBuffer.class) { 980 return LongBuffer.wrap(new long[1]); 981 } else if (c == DoubleBuffer.class) { 982 return DoubleBuffer.wrap(new double[1]); 983 } else { 984 return null; 985 } 986 } 987 988 @DataProvider(name = "bufferSources") 989 public static Object[][] bufferSources() { 990 Predicate<MemorySegment> heapTest = segment -> segment instanceof HeapMemorySegmentImpl; 991 Predicate<MemorySegment> nativeTest = segment -> segment instanceof NativeMemorySegmentImpl; 992 Predicate<MemorySegment> mappedTest = segment -> segment instanceof MappedMemorySegmentImpl; 993 try (FileChannel channel = FileChannel.open(tempPath, StandardOpenOption.READ, StandardOpenOption.WRITE)) { 994 return new Object[][]{ 995 { ByteBuffer.wrap(new byte[256]), heapTest }, 996 { ByteBuffer.allocate(256), heapTest }, 997 { ByteBuffer.allocateDirect(256), nativeTest }, 998 { channel.map(FileChannel.MapMode.READ_WRITE, 0L, 256), mappedTest }, 999 1000 { ByteBuffer.wrap(new byte[256]).asReadOnlyBuffer(), heapTest }, 1001 { ByteBuffer.allocate(256).asReadOnlyBuffer(), heapTest }, 1002 { ByteBuffer.allocateDirect(256).asReadOnlyBuffer(), nativeTest }, 1003 { channel.map(FileChannel.MapMode.READ_WRITE, 0L, 256).asReadOnlyBuffer(), 1004 nativeTest /* this seems to be an existing bug in the BB implementation */ } 1005 }; 1006 } catch (IOException ex) { 1007 throw new ExceptionInInitializerError(ex); 1008 } 1009 } 1010 1011 enum MappedSegmentOp { 1012 LOAD(MemorySegment::load), 1013 UNLOAD(MemorySegment::unload), 1014 IS_LOADED(MemorySegment::isLoaded), 1015 FORCE(MemorySegment::force), 1016 BUFFER_LOAD(m -> ((MappedByteBuffer)m.asByteBuffer()).load()), 1017 BUFFER_IS_LOADED(m -> ((MappedByteBuffer)m.asByteBuffer()).isLoaded()), 1018 BUFFER_FORCE(m -> ((MappedByteBuffer)m.asByteBuffer()).force()); 1019 1020 1021 private final Consumer<MemorySegment> segmentOp; 1022 1023 MappedSegmentOp(Consumer<MemorySegment> segmentOp) { 1024 this.segmentOp = segmentOp; 1025 } 1026 1027 void apply(MemorySegment segment) { 1028 segmentOp.accept(segment); 1029 } 1030 } 1031 1032 @DataProvider(name = "mappedOps") 1033 public static Object[][] mappedOps() { 1034 return Stream.of(MappedSegmentOp.values()) 1035 .map(op -> new Object[] { op }) 1036 .toArray(Object[][]::new); 1037 } 1038 1039 @DataProvider(name = "bufferFactories") 1040 public static Object[][] bufferFactories() { 1041 List<Supplier<Buffer>> l = List.of( 1042 () -> ByteBuffer.allocate(10), 1043 () -> CharBuffer.allocate(10), 1044 () -> ShortBuffer.allocate(10), 1045 () -> IntBuffer.allocate(10), 1046 () -> FloatBuffer.allocate(10), 1047 () -> LongBuffer.allocate(10), 1048 () -> DoubleBuffer.allocate(10), 1049 () -> ByteBuffer.allocateDirect(10), 1050 () -> ByteBuffer.allocateDirect(10).asCharBuffer(), 1051 () -> ByteBuffer.allocateDirect(10).asShortBuffer(), 1052 () -> ByteBuffer.allocateDirect(10).asIntBuffer(), 1053 () -> ByteBuffer.allocateDirect(10).asFloatBuffer(), 1054 () -> ByteBuffer.allocateDirect(10).asLongBuffer(), 1055 () -> ByteBuffer.allocateDirect(10).asDoubleBuffer() 1056 ); 1057 return l.stream().map(s -> new Object[] { s }).toArray(Object[][]::new); 1058 1059 } 1060 @DataProvider(name = "fromArrays") 1061 public static Object[][] fromArrays() { 1062 int len = 16; 1063 return Stream.of( 1064 MemorySegment.ofArray(new byte[len]), 1065 MemorySegment.ofArray(new short[len]), 1066 MemorySegment.ofArray(new char[len]), 1067 MemorySegment.ofArray(new int[len]), 1068 MemorySegment.ofArray(new long[len]), 1069 MemorySegment.ofArray(new float[len]), 1070 MemorySegment.ofArray(new double[len]) 1071 ) 1072 .map(s -> new Object[] { s }) 1073 .toArray(Object[][]::new); 1074 } 1075 }