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