< prev index next >

test/jdk/java/foreign/TestByteBuffer.java

Print this page

 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
 27  *          jdk.incubator.foreign/jdk.internal.foreign
 28  * @run testng/othervm --enable-native-access=ALL-UNNAMED TestByteBuffer
 29  */
 30 
 31 import jdk.incubator.foreign.MemoryAccess;
 32 import jdk.incubator.foreign.MemoryLayouts;
 33 import jdk.incubator.foreign.MemoryLayout;
 34 import jdk.incubator.foreign.MemoryAddress;
 35 import jdk.incubator.foreign.MemorySegment;
 36 import jdk.incubator.foreign.MemoryLayout.PathElement;
 37 import jdk.incubator.foreign.ResourceScope;
 38 import jdk.incubator.foreign.SequenceLayout;
 39 
 40 import java.io.File;
 41 import java.io.IOException;
 42 import java.lang.invoke.MethodHandle;
 43 import java.lang.invoke.MethodHandles;
 44 import java.lang.invoke.VarHandle;
 45 import java.lang.ref.Cleaner;
 46 import java.lang.ref.WeakReference;
 47 import java.lang.reflect.InvocationTargetException;
 48 import java.lang.reflect.Method;
 49 import java.lang.reflect.Modifier;
 50 import java.net.URI;
 51 import java.nio.Buffer;
 52 import java.nio.ByteBuffer;

 65 import java.util.ArrayList;
 66 import java.util.Arrays;
 67 import java.util.HashMap;
 68 import java.util.List;
 69 import java.util.Map;
 70 import java.util.function.BiConsumer;
 71 import java.util.function.BiFunction;
 72 import java.util.function.Consumer;
 73 import java.util.function.Function;
 74 import java.util.function.Predicate;
 75 import java.util.function.Supplier;
 76 import java.util.stream.Stream;
 77 
 78 import jdk.internal.foreign.HeapMemorySegmentImpl;
 79 import jdk.internal.foreign.MappedMemorySegmentImpl;
 80 import jdk.internal.foreign.NativeMemorySegmentImpl;
 81 import org.testng.SkipException;
 82 import org.testng.annotations.*;
 83 import sun.nio.ch.DirectBuffer;
 84 







 85 import static org.testng.Assert.*;
 86 
 87 public class TestByteBuffer {
 88 
 89     static Path tempPath;
 90 
 91     static {
 92         try {
 93             File file = File.createTempFile("buffer", "txt");
 94             file.deleteOnExit();
 95             tempPath = file.toPath();
 96             Files.write(file.toPath(), new byte[256], StandardOpenOption.WRITE);
 97 
 98         } catch (IOException ex) {
 99             throw new ExceptionInInitializerError(ex);
100         }
101     }
102 
103     static SequenceLayout tuples = MemoryLayout.sequenceLayout(500,
104             MemoryLayout.structLayout(
105                     MemoryLayouts.BITS_32_BE.withName("index"),
106                     MemoryLayouts.BITS_32_BE.withName("value")
107             ));
108 
109     static SequenceLayout bytes = MemoryLayout.sequenceLayout(100,
110             MemoryLayouts.BITS_8_BE
111     );
112 
113     static SequenceLayout chars = MemoryLayout.sequenceLayout(100,
114             MemoryLayouts.BITS_16_BE
115     );
116 
117     static SequenceLayout shorts = MemoryLayout.sequenceLayout(100,
118             MemoryLayouts.BITS_16_BE
119     );
120 
121     static SequenceLayout ints = MemoryLayout.sequenceLayout(100,
122             MemoryLayouts.BITS_32_BE
123     );
124 
125     static SequenceLayout floats = MemoryLayout.sequenceLayout(100,
126             MemoryLayouts.BITS_32_BE
127     );
128 
129     static SequenceLayout longs = MemoryLayout.sequenceLayout(100,
130             MemoryLayouts.BITS_64_BE
131     );
132 
133     static SequenceLayout doubles = MemoryLayout.sequenceLayout(100,
134             MemoryLayouts.BITS_64_BE
135     );
136 
137     static VarHandle indexHandle = tuples.varHandle(int.class, PathElement.sequenceElement(), PathElement.groupElement("index"));
138     static VarHandle valueHandle = tuples.varHandle(float.class, PathElement.sequenceElement(), PathElement.groupElement("value"));
139 
140     static void initTuples(MemorySegment base, long count) {
141         for (long i = 0; i < count ; i++) {
142             indexHandle.set(base, i, (int)i);
143             valueHandle.set(base, i, (float)(i / 500f));
144         }
145     }
146 
147     static void checkTuples(MemorySegment base, ByteBuffer bb, long count) {
148         for (long i = 0; i < count ; i++) {
149             int index;
150             float value;
151             assertEquals(index = bb.getInt(), (int)indexHandle.get(base, i));
152             assertEquals(value = bb.getFloat(), (float)valueHandle.get(base, i));
153             assertEquals(value, index / 500f);
154         }
155     }
156 
157     static void initBytes(MemorySegment base, SequenceLayout seq, BiConsumer<MemorySegment, Long> handleSetter) {
158         for (long i = 0; i < seq.elementCount().getAsLong() ; i++) {

246     @Test
247     public void testMappedSegment() throws Throwable {
248         File f = new File("test2.out");
249         f.createNewFile();
250         f.deleteOnExit();
251 
252         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
253             //write to channel
254             MemorySegment segment = MemorySegment.mapFile(f.toPath(), 0L, tuples.byteSize(), FileChannel.MapMode.READ_WRITE, scope);
255             initTuples(segment, tuples.elementCount().getAsLong());
256             segment.force();
257         }
258 
259         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
260             //read from channel
261             MemorySegment segment = MemorySegment.mapFile(f.toPath(), 0L, tuples.byteSize(), FileChannel.MapMode.READ_ONLY, scope);
262             checkTuples(segment, segment.asByteBuffer(), tuples.elementCount().getAsLong());
263         }
264     }
265 
266     @Test(dataProvider = "mappedOps", expectedExceptions = UnsupportedOperationException.class)
267     public void testMappedSegmentOperations(MappedSegmentOp mappedBufferOp) throws Throwable {
268         File f = new File("test3.out");
269         f.createNewFile();
270         f.deleteOnExit();
271 
272         MemorySegment segment = MemorySegment.mapFile(f.toPath(), 0L, 8, FileChannel.MapMode.READ_WRITE, ResourceScope.newImplicitScope());
273         assertTrue(segment.isMapped());
274         segment.scope().close();
275         mappedBufferOp.apply(segment);
276     }
277 
278     @Test
279     public void testMappedSegmentOffset() throws Throwable {
280         File f = new File("test3.out");
281         f.createNewFile();
282         f.deleteOnExit();
283 
284         MemoryLayout tupleLayout = tuples.elementLayout();
285 
286         // write one at a time

307 
308     @Test
309     public void testLargeMappedSegment() throws Throwable {
310         if (System.getProperty("sun.arch.data.model").equals("32")) {
311             throw new SkipException("large mapped files not supported on 32-bit systems");
312         }
313 
314         File f = new File("testLargeMappedSegment.out");
315         f.createNewFile();
316         f.deleteOnExit();
317 
318         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
319             MemorySegment segment = MemorySegment.mapFile(f.toPath(), 0, LARGE_SIZE, FileChannel.MapMode.READ_WRITE, scope);
320             segment.isLoaded();
321             segment.load();
322             segment.isLoaded();
323             segment.force();
324             segment.isLoaded();
325             segment.unload();
326             segment.isLoaded();



327         }
328     }
329 
330     static void withMappedBuffer(FileChannel channel, FileChannel.MapMode mode, long pos, long size, Consumer<MappedByteBuffer> action) throws Throwable {
331         MappedByteBuffer mbb = channel.map(mode, pos, size);
332         var ref = new WeakReference<>(mbb);
333         action.accept(mbb);
334         mbb = null;
335         //wait for it to be GCed
336         System.gc();
337         while (ref.get() != null) {
338             Thread.sleep(20);
339         }
340     }
341 
342     static void checkByteArrayAlignment(MemoryLayout layout) {
343         if (layout.bitSize() > 32
344                 && System.getProperty("sun.arch.data.model").equals("32")) {
345             throw new SkipException("avoid unaligned access on 32-bit system");
346         }

463         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
464             MemorySegment segment = MemorySegment.allocateNative(seq, scope);
465             initializer.accept(segment);
466             MemorySegment second = MemorySegment.ofByteBuffer(segment.asByteBuffer());
467             checker.accept(second);
468         }
469     }
470 
471     @Test(expectedExceptions = IllegalStateException.class)
472     public void testBufferOnClosedScope() {
473         MemorySegment leaked;
474         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
475             leaked = MemorySegment.allocateNative(bytes, scope);
476         }
477         ByteBuffer byteBuffer = leaked.asByteBuffer(); // ok
478         byteBuffer.get(); // should throw
479     }
480 
481     @Test(expectedExceptions = IllegalStateException.class)
482     public void testTooBigForByteBuffer() {
483         MemorySegment segment = MemoryAddress.NULL.asSegment(Integer.MAX_VALUE + 10L, ResourceScope.globalScope());
484         segment.asByteBuffer();
485     }
486 
487     @Test(expectedExceptions = IllegalArgumentException.class)
488     public void testBadMapNegativeSize() throws IOException {
489         File f = new File("testNeg1.out");
490         f.createNewFile();
491         f.deleteOnExit();
492         MemorySegment.mapFile(f.toPath(), 0L, -1, FileChannel.MapMode.READ_WRITE, ResourceScope.newImplicitScope());
493     }
494 
495     @Test(expectedExceptions = IllegalArgumentException.class)
496     public void testBadMapNegativeOffset() throws IOException {
497         File f = new File("testNeg2.out");
498         f.createNewFile();
499         f.deleteOnExit();
500         MemorySegment.mapFile(f.toPath(), -1, 1, FileChannel.MapMode.READ_WRITE, ResourceScope.newImplicitScope());
501     }
502 
503     @Test
504     public void testMapOffset() throws IOException {
505         File f = new File("testMapOffset.out");
506         f.createNewFile();
507         f.deleteOnExit();
508 
509         int SIZE = Byte.MAX_VALUE;
510 
511         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
512             MemorySegment segment = MemorySegment.mapFile(f.toPath(), 0, SIZE, FileChannel.MapMode.READ_WRITE, scope);
513             for (byte offset = 0; offset < SIZE; offset++) {
514                 MemoryAccess.setByteAtOffset(segment, offset, offset);
515             }
516             segment.force();
517         }
518 
519         for (int offset = 0 ; offset < SIZE ; offset++) {
520             try (ResourceScope scope = ResourceScope.newConfinedScope()) {
521                 MemorySegment segment = MemorySegment.mapFile(f.toPath(), offset, SIZE - offset, FileChannel.MapMode.READ_ONLY, scope);
522                 assertEquals(MemoryAccess.getByte(segment), offset);
523             }
524         }
525     }
526 
527     @Test
528     public void testMapZeroSize() throws IOException {
529         File f = new File("testPos1.out");
530         f.createNewFile();
531         f.deleteOnExit();
532         //RW
533         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
534             MemorySegment segment = MemorySegment.mapFile(f.toPath(), 0L, 0L, FileChannel.MapMode.READ_WRITE, scope);
535             assertEquals(segment.byteSize(), 0);
536             assertEquals(segment.isMapped(), true);
537             assertFalse(segment.isReadOnly());
538             segment.force();
539             segment.load();
540             segment.isLoaded();
541             segment.unload();
542         }

619     public void bufferProperties(ByteBuffer bb, Predicate<MemorySegment> _unused) {
620         MemorySegment segment = MemorySegment.ofByteBuffer(bb);
621         ByteBuffer buffer = segment.asByteBuffer();
622         assertEquals(buffer.position(), 0);
623         assertEquals(buffer.capacity(), segment.byteSize());
624         assertEquals(buffer.limit(), segment.byteSize());
625     }
626 
627     @Test
628     public void testRoundTripAccess() {
629         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
630             MemorySegment ms = MemorySegment.allocateNative(4, 1, scope);
631             MemorySegment msNoAccess = ms.asReadOnly();
632             MemorySegment msRoundTrip = MemorySegment.ofByteBuffer(msNoAccess.asByteBuffer());
633             assertEquals(msNoAccess.isReadOnly(), msRoundTrip.isReadOnly());
634         }
635     }
636 
637     @Test(expectedExceptions = IllegalStateException.class)
638     public void testDeadAccessOnClosedBufferSegment() {
639         MemorySegment s1 = MemorySegment.allocateNative(MemoryLayouts.JAVA_INT, ResourceScope.newConfinedScope());
640         MemorySegment s2 = MemorySegment.ofByteBuffer(s1.asByteBuffer());
641 
642         // memory freed
643         s1.scope().close();
644 
645         MemoryAccess.setInt(s2, 10); // Dead access!
646     }
647 
648     @Test(dataProvider = "allScopes")
649     public void testIOOnSegmentBuffer(Supplier<ResourceScope> scopeSupplier) throws IOException {
650         File tmp = File.createTempFile("tmp", "txt");
651         tmp.deleteOnExit();
652         ResourceScope scope;
653         try (FileChannel channel = FileChannel.open(tmp.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE) ;
654              ResourceScope scp = closeableScopeOrNull(scope = scopeSupplier.get())) {
655             MemorySegment segment = MemorySegment.allocateNative(10, 1, scope);
656             for (int i = 0; i < 10; i++) {
657                 MemoryAccess.setByteAtOffset(segment, i, (byte) i);
658             }
659             ByteBuffer bb = segment.asByteBuffer();
660             assertEquals(channel.write(bb), 10);
661             segment.fill((byte)0x00);
662             assertEquals(bb.clear(), ByteBuffer.wrap(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}));
663             assertEquals(channel.position(0).read(bb.clear()), 10);
664             assertEquals(bb.flip(), ByteBuffer.wrap(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}));
665         }
666     }
667 
668     static final Class<IllegalStateException> ISE = IllegalStateException.class;
669 
670     @Test(dataProvider = "closeableScopes")
671     public void testIOOnClosedSegmentBuffer(Supplier<ResourceScope> scopeSupplier) throws IOException {
672         File tmp = File.createTempFile("tmp", "txt");
673         tmp.deleteOnExit();
674         try (FileChannel channel = FileChannel.open(tmp.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) {
675             MemorySegment segment = MemorySegment.allocateNative(10, scopeSupplier.get());
676             for (int i = 0; i < 10; i++) {
677                 MemoryAccess.setByteAtOffset(segment, i, (byte) i);
678             }
679             ByteBuffer bb = segment.asByteBuffer();
680             segment.scope().close();
681             assertThrows(ISE, () -> channel.read(bb));
682             assertThrows(ISE, () -> channel.read(new ByteBuffer[] {bb}));
683             assertThrows(ISE, () -> channel.read(new ByteBuffer[] {bb}, 0, 1));
684             assertThrows(ISE, () -> channel.write(bb));
685             assertThrows(ISE, () -> channel.write(new ByteBuffer[] {bb}));
686             assertThrows(ISE, () -> channel.write(new ByteBuffer[] {bb}, 0 ,1));
687         }
688     }
689 
690     @Test
691     public void buffersAndArraysFromSlices() {
692         try (ResourceScope scope = ResourceScope.newSharedScope()) {
693             MemorySegment segment = MemorySegment.allocateNative(16, scope);
694             int newSize = 8;
695             var slice = segment.asSlice(4, newSize);
696 
697             var bytes = slice.toByteArray();
698             assertEquals(newSize, bytes.length);
699 
700             var buffer = slice.asByteBuffer();
701             // Fails for heap segments, but passes for native segments:
702             assertEquals(0, buffer.position());
703             assertEquals(newSize, buffer.limit());
704             assertEquals(newSize, buffer.capacity());
705         }
706     }
707 
708     @Test
709     public void viewsFromSharedSegment() {
710         try (ResourceScope scope = ResourceScope.newSharedScope()) {
711             MemorySegment segment = MemorySegment.allocateNative(16, scope);
712             var byteBuffer = segment.asByteBuffer();
713             byteBuffer.asReadOnlyBuffer();
714             byteBuffer.slice(0, 8);
715         }
716     }
717 
718     @DataProvider(name = "segments")
719     public static Object[][] segments() throws Throwable {
720         return new Object[][] {
721                 { (Supplier<MemorySegment>) () -> MemorySegment.allocateNative(16, ResourceScope.newImplicitScope()) },

722                 { (Supplier<MemorySegment>) () -> MemorySegment.ofArray(new byte[16]) }
723         };
724     }
725 
726     @DataProvider(name = "closeableScopes")
727     public static Object[][] closeableScopes() {
728         return new Object[][] {
729                 { (Supplier<ResourceScope>) () -> ResourceScope.newSharedScope()   },
730                 { (Supplier<ResourceScope>) () -> ResourceScope.newConfinedScope() },
731                 { (Supplier<ResourceScope>) () -> ResourceScope.newSharedScope(Cleaner.create())   },
732                 { (Supplier<ResourceScope>) () -> ResourceScope.newConfinedScope(Cleaner.create()) }
733         };
734     }
735 
736     @DataProvider(name = "implicitScopes")
737     public static Object[][] implicitScopes() {
738         return new Object[][] {
739                 { (Supplier<ResourceScope>) ResourceScope::newImplicitScope },
740                 { (Supplier<ResourceScope>) ResourceScope::globalScope      },
741         };
742     }
743 
744     @DataProvider(name = "allScopes")
745     public static Object[][] allScopes() {
746         return Stream.of(implicitScopes(), closeableScopes())
747                 .flatMap(Arrays::stream)
748                 .toArray(Object[][]::new);
749     }
750 
751     static ResourceScope closeableScopeOrNull(ResourceScope scope) {
752         if (scope.isImplicit())
753             return null;
754         return scope;
755     }
756 
757     @DataProvider(name = "bufferOps")
758     public static Object[][] bufferOps() throws Throwable {
759         List<Object[]> args = new ArrayList<>();
760         bufferOpsArgs(args, bb -> bb, ByteBuffer.class);
761         bufferOpsArgs(args, ByteBuffer::asCharBuffer, CharBuffer.class);
762         bufferOpsArgs(args, ByteBuffer::asShortBuffer, ShortBuffer.class);
763         bufferOpsArgs(args, ByteBuffer::asIntBuffer, IntBuffer.class);
764         bufferOpsArgs(args, ByteBuffer::asFloatBuffer, FloatBuffer.class);
765         bufferOpsArgs(args, ByteBuffer::asLongBuffer, LongBuffer.class);
766         bufferOpsArgs(args, ByteBuffer::asDoubleBuffer, DoubleBuffer.class);
767         return args.toArray(Object[][]::new);
768     }
769 
770     static void bufferOpsArgs(List<Object[]> argsList, Function<ByteBuffer, Buffer> factory, Class<?> bufferClass) {
771         for (Method m : bufferClass.getMethods()) {
772             //skip statics and method declared in j.l.Object

795 
796     static Map<MethodHandle, Object[]> varHandleMembers(ByteBuffer bb, VarHandle handle) {
797         Map<MethodHandle, Object[]> members = new HashMap<>();
798         for (VarHandle.AccessMode mode : VarHandle.AccessMode.values()) {
799             Class<?>[] params = handle.accessModeType(mode).parameterArray();
800             Object[] args = Stream.concat(Stream.of(bb), Stream.of(params).skip(1)
801                     .map(TestByteBuffer::defaultValue))
802                     .toArray();
803             try {
804                 members.put(MethodHandles.varHandleInvoker(mode, handle.accessModeType(mode)), args);
805             } catch (Throwable ex) {
806                 throw new AssertionError(ex);
807             }
808         }
809         return members;
810     }
811 
812     @DataProvider(name = "resizeOps")
813     public Object[][] resizeOps() {
814         Consumer<MemorySegment> byteInitializer =
815                 (base) -> initBytes(base, bytes, (addr, pos) -> MemoryAccess.setByteAtOffset(addr, pos, (byte)(long)pos));
816         Consumer<MemorySegment> charInitializer =
817                 (base) -> initBytes(base, chars, (addr, pos) -> MemoryAccess.setCharAtIndex(addr, pos, ByteOrder.BIG_ENDIAN, (char)(long)pos));
818         Consumer<MemorySegment> shortInitializer =
819                 (base) -> initBytes(base, shorts, (addr, pos) -> MemoryAccess.setShortAtIndex(addr, pos, ByteOrder.BIG_ENDIAN, (short)(long)pos));
820         Consumer<MemorySegment> intInitializer =
821                 (base) -> initBytes(base, ints, (addr, pos) -> MemoryAccess.setIntAtIndex(addr, pos, ByteOrder.BIG_ENDIAN, (int)(long)pos));
822         Consumer<MemorySegment> floatInitializer =
823                 (base) -> initBytes(base, floats, (addr, pos) -> MemoryAccess.setFloatAtIndex(addr, pos, ByteOrder.BIG_ENDIAN, (float)(long)pos));
824         Consumer<MemorySegment> longInitializer =
825                 (base) -> initBytes(base, longs, (addr, pos) -> MemoryAccess.setLongAtIndex(addr, pos, ByteOrder.BIG_ENDIAN, (long)pos));
826         Consumer<MemorySegment> doubleInitializer =
827                 (base) -> initBytes(base, doubles, (addr, pos) -> MemoryAccess.setDoubleAtIndex(addr, pos, ByteOrder.BIG_ENDIAN, (double)(long)pos));
828 
829         Consumer<MemorySegment> byteChecker =
830                 (base) -> checkBytes(base, bytes, Function.identity(), (addr, pos) -> MemoryAccess.getByteAtOffset(addr, pos), ByteBuffer::get);
831         Consumer<MemorySegment> charChecker =
832                 (base) -> checkBytes(base, chars, ByteBuffer::asCharBuffer, (addr, pos) -> MemoryAccess.getCharAtIndex(addr, pos, ByteOrder.BIG_ENDIAN), CharBuffer::get);
833         Consumer<MemorySegment> shortChecker =
834                 (base) -> checkBytes(base, shorts, ByteBuffer::asShortBuffer, (addr, pos) -> MemoryAccess.getShortAtIndex(addr, pos, ByteOrder.BIG_ENDIAN), ShortBuffer::get);
835         Consumer<MemorySegment> intChecker =
836                 (base) -> checkBytes(base, ints, ByteBuffer::asIntBuffer, (addr, pos) -> MemoryAccess.getIntAtIndex(addr, pos, ByteOrder.BIG_ENDIAN), IntBuffer::get);
837         Consumer<MemorySegment> floatChecker =
838                 (base) -> checkBytes(base, floats, ByteBuffer::asFloatBuffer, (addr, pos) -> MemoryAccess.getFloatAtIndex(addr, pos, ByteOrder.BIG_ENDIAN), FloatBuffer::get);
839         Consumer<MemorySegment> longChecker =
840                 (base) -> checkBytes(base, longs, ByteBuffer::asLongBuffer, (addr, pos) -> MemoryAccess.getLongAtIndex(addr, pos, ByteOrder.BIG_ENDIAN), LongBuffer::get);
841         Consumer<MemorySegment> doubleChecker =
842                 (base) -> checkBytes(base, doubles, ByteBuffer::asDoubleBuffer, (addr, pos) -> MemoryAccess.getDoubleAtIndex(addr, pos, ByteOrder.BIG_ENDIAN), DoubleBuffer::get);
843 
844         return new Object[][]{
845                 {byteChecker, byteInitializer, bytes},
846                 {charChecker, charInitializer, chars},
847                 {shortChecker, shortInitializer, shorts},
848                 {intChecker, intInitializer, ints},
849                 {floatChecker, floatInitializer, floats},
850                 {longChecker, longInitializer, longs},
851                 {doubleChecker, doubleInitializer, doubles}
852         };
853     }
854 
855     static Object defaultValue(Class<?> c) {
856         if (c.isPrimitive()) {
857             if (c == char.class) {
858                 return (char)0;
859             } else if (c == boolean.class) {
860                 return false;
861             } else if (c == byte.class) {
862                 return (byte)0;

 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
 27  *          jdk.incubator.foreign/jdk.internal.foreign
 28  * @run testng/othervm --enable-native-access=ALL-UNNAMED TestByteBuffer
 29  */
 30 


 31 import jdk.incubator.foreign.MemoryLayout;
 32 import jdk.incubator.foreign.MemoryAddress;
 33 import jdk.incubator.foreign.MemorySegment;
 34 import jdk.incubator.foreign.MemoryLayout.PathElement;
 35 import jdk.incubator.foreign.ResourceScope;
 36 import jdk.incubator.foreign.SequenceLayout;
 37 
 38 import java.io.File;
 39 import java.io.IOException;
 40 import java.lang.invoke.MethodHandle;
 41 import java.lang.invoke.MethodHandles;
 42 import java.lang.invoke.VarHandle;
 43 import java.lang.ref.Cleaner;
 44 import java.lang.ref.WeakReference;
 45 import java.lang.reflect.InvocationTargetException;
 46 import java.lang.reflect.Method;
 47 import java.lang.reflect.Modifier;
 48 import java.net.URI;
 49 import java.nio.Buffer;
 50 import java.nio.ByteBuffer;

 63 import java.util.ArrayList;
 64 import java.util.Arrays;
 65 import java.util.HashMap;
 66 import java.util.List;
 67 import java.util.Map;
 68 import java.util.function.BiConsumer;
 69 import java.util.function.BiFunction;
 70 import java.util.function.Consumer;
 71 import java.util.function.Function;
 72 import java.util.function.Predicate;
 73 import java.util.function.Supplier;
 74 import java.util.stream.Stream;
 75 
 76 import jdk.internal.foreign.HeapMemorySegmentImpl;
 77 import jdk.internal.foreign.MappedMemorySegmentImpl;
 78 import jdk.internal.foreign.NativeMemorySegmentImpl;
 79 import org.testng.SkipException;
 80 import org.testng.annotations.*;
 81 import sun.nio.ch.DirectBuffer;
 82 
 83 import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE;
 84 import static jdk.incubator.foreign.ValueLayout.JAVA_CHAR;
 85 import static jdk.incubator.foreign.ValueLayout.JAVA_DOUBLE;
 86 import static jdk.incubator.foreign.ValueLayout.JAVA_FLOAT;
 87 import static jdk.incubator.foreign.ValueLayout.JAVA_INT;
 88 import static jdk.incubator.foreign.ValueLayout.JAVA_LONG;
 89 import static jdk.incubator.foreign.ValueLayout.JAVA_SHORT;
 90 import static org.testng.Assert.*;
 91 
 92 public class TestByteBuffer {
 93 
 94     static Path tempPath;
 95 
 96     static {
 97         try {
 98             File file = File.createTempFile("buffer", "txt");
 99             file.deleteOnExit();
100             tempPath = file.toPath();
101             Files.write(file.toPath(), new byte[256], StandardOpenOption.WRITE);
102 
103         } catch (IOException ex) {
104             throw new ExceptionInInitializerError(ex);
105         }
106     }
107 
108     static SequenceLayout tuples = MemoryLayout.sequenceLayout(500,
109             MemoryLayout.structLayout(
110                     JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withName("index"),
111                     JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN).withName("value")
112             ));
113 
114     static SequenceLayout bytes = MemoryLayout.sequenceLayout(100,
115             JAVA_BYTE
116     );
117 
118     static SequenceLayout chars = MemoryLayout.sequenceLayout(100,
119             JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN)
120     );
121 
122     static SequenceLayout shorts = MemoryLayout.sequenceLayout(100,
123             JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN)
124     );
125 
126     static SequenceLayout ints = MemoryLayout.sequenceLayout(100,
127             JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN)
128     );
129 
130     static SequenceLayout floats = MemoryLayout.sequenceLayout(100,
131             JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN)
132     );
133 
134     static SequenceLayout longs = MemoryLayout.sequenceLayout(100,
135             JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN)
136     );
137 
138     static SequenceLayout doubles = MemoryLayout.sequenceLayout(100,
139             JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN)
140     );
141 
142     static VarHandle indexHandle = tuples.varHandle(PathElement.sequenceElement(), PathElement.groupElement("index"));
143     static VarHandle valueHandle = tuples.varHandle(PathElement.sequenceElement(), PathElement.groupElement("value"));
144 
145     static void initTuples(MemorySegment base, long count) {
146         for (long i = 0; i < count ; i++) {
147             indexHandle.set(base, i, (int)i);
148             valueHandle.set(base, i, (float)(i / 500f));
149         }
150     }
151 
152     static void checkTuples(MemorySegment base, ByteBuffer bb, long count) {
153         for (long i = 0; i < count ; i++) {
154             int index;
155             float value;
156             assertEquals(index = bb.getInt(), (int)indexHandle.get(base, i));
157             assertEquals(value = bb.getFloat(), (float)valueHandle.get(base, i));
158             assertEquals(value, index / 500f);
159         }
160     }
161 
162     static void initBytes(MemorySegment base, SequenceLayout seq, BiConsumer<MemorySegment, Long> handleSetter) {
163         for (long i = 0; i < seq.elementCount().getAsLong() ; i++) {

251     @Test
252     public void testMappedSegment() throws Throwable {
253         File f = new File("test2.out");
254         f.createNewFile();
255         f.deleteOnExit();
256 
257         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
258             //write to channel
259             MemorySegment segment = MemorySegment.mapFile(f.toPath(), 0L, tuples.byteSize(), FileChannel.MapMode.READ_WRITE, scope);
260             initTuples(segment, tuples.elementCount().getAsLong());
261             segment.force();
262         }
263 
264         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
265             //read from channel
266             MemorySegment segment = MemorySegment.mapFile(f.toPath(), 0L, tuples.byteSize(), FileChannel.MapMode.READ_ONLY, scope);
267             checkTuples(segment, segment.asByteBuffer(), tuples.elementCount().getAsLong());
268         }
269     }
270 
271     @Test(dataProvider = "mappedOps", expectedExceptions = IllegalStateException.class)
272     public void testMappedSegmentOperations(MappedSegmentOp mappedBufferOp) throws Throwable {
273         File f = new File("test3.out");
274         f.createNewFile();
275         f.deleteOnExit();
276 
277         MemorySegment segment = MemorySegment.mapFile(f.toPath(), 0L, 8, FileChannel.MapMode.READ_WRITE, ResourceScope.newImplicitScope());
278         assertTrue(segment.isMapped());
279         segment.scope().close();
280         mappedBufferOp.apply(segment);
281     }
282 
283     @Test
284     public void testMappedSegmentOffset() throws Throwable {
285         File f = new File("test3.out");
286         f.createNewFile();
287         f.deleteOnExit();
288 
289         MemoryLayout tupleLayout = tuples.elementLayout();
290 
291         // write one at a time

312 
313     @Test
314     public void testLargeMappedSegment() throws Throwable {
315         if (System.getProperty("sun.arch.data.model").equals("32")) {
316             throw new SkipException("large mapped files not supported on 32-bit systems");
317         }
318 
319         File f = new File("testLargeMappedSegment.out");
320         f.createNewFile();
321         f.deleteOnExit();
322 
323         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
324             MemorySegment segment = MemorySegment.mapFile(f.toPath(), 0, LARGE_SIZE, FileChannel.MapMode.READ_WRITE, scope);
325             segment.isLoaded();
326             segment.load();
327             segment.isLoaded();
328             segment.force();
329             segment.isLoaded();
330             segment.unload();
331             segment.isLoaded();
332         } catch(IOException e) {
333             if (e.getMessage().equals("Function not implemented"))
334                 throw new SkipException(e.getMessage(), e);
335         }
336     }
337 
338     static void withMappedBuffer(FileChannel channel, FileChannel.MapMode mode, long pos, long size, Consumer<MappedByteBuffer> action) throws Throwable {
339         MappedByteBuffer mbb = channel.map(mode, pos, size);
340         var ref = new WeakReference<>(mbb);
341         action.accept(mbb);
342         mbb = null;
343         //wait for it to be GCed
344         System.gc();
345         while (ref.get() != null) {
346             Thread.sleep(20);
347         }
348     }
349 
350     static void checkByteArrayAlignment(MemoryLayout layout) {
351         if (layout.bitSize() > 32
352                 && System.getProperty("sun.arch.data.model").equals("32")) {
353             throw new SkipException("avoid unaligned access on 32-bit system");
354         }

471         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
472             MemorySegment segment = MemorySegment.allocateNative(seq, scope);
473             initializer.accept(segment);
474             MemorySegment second = MemorySegment.ofByteBuffer(segment.asByteBuffer());
475             checker.accept(second);
476         }
477     }
478 
479     @Test(expectedExceptions = IllegalStateException.class)
480     public void testBufferOnClosedScope() {
481         MemorySegment leaked;
482         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
483             leaked = MemorySegment.allocateNative(bytes, scope);
484         }
485         ByteBuffer byteBuffer = leaked.asByteBuffer(); // ok
486         byteBuffer.get(); // should throw
487     }
488 
489     @Test(expectedExceptions = IllegalStateException.class)
490     public void testTooBigForByteBuffer() {
491         MemorySegment segment = MemorySegment.ofAddressNative(MemoryAddress.NULL, Integer.MAX_VALUE + 10L, ResourceScope.newImplicitScope());
492         segment.asByteBuffer();
493     }
494 
495     @Test(expectedExceptions = IllegalArgumentException.class)
496     public void testBadMapNegativeSize() throws IOException {
497         File f = new File("testNeg1.out");
498         f.createNewFile();
499         f.deleteOnExit();
500         MemorySegment.mapFile(f.toPath(), 0L, -1, FileChannel.MapMode.READ_WRITE, ResourceScope.newImplicitScope());
501     }
502 
503     @Test(expectedExceptions = IllegalArgumentException.class)
504     public void testBadMapNegativeOffset() throws IOException {
505         File f = new File("testNeg2.out");
506         f.createNewFile();
507         f.deleteOnExit();
508         MemorySegment.mapFile(f.toPath(), -1, 1, FileChannel.MapMode.READ_WRITE, ResourceScope.newImplicitScope());
509     }
510 
511     @Test
512     public void testMapOffset() throws IOException {
513         File f = new File("testMapOffset.out");
514         f.createNewFile();
515         f.deleteOnExit();
516 
517         int SIZE = Byte.MAX_VALUE;
518 
519         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
520             MemorySegment segment = MemorySegment.mapFile(f.toPath(), 0, SIZE, FileChannel.MapMode.READ_WRITE, scope);
521             for (byte offset = 0; offset < SIZE; offset++) {
522                 segment.set(JAVA_BYTE, offset, offset);
523             }
524             segment.force();
525         }
526 
527         for (int offset = 0 ; offset < SIZE ; offset++) {
528             try (ResourceScope scope = ResourceScope.newConfinedScope()) {
529                 MemorySegment segment = MemorySegment.mapFile(f.toPath(), offset, SIZE - offset, FileChannel.MapMode.READ_ONLY, scope);
530                 assertEquals(segment.get(JAVA_BYTE, 0), offset);
531             }
532         }
533     }
534 
535     @Test
536     public void testMapZeroSize() throws IOException {
537         File f = new File("testPos1.out");
538         f.createNewFile();
539         f.deleteOnExit();
540         //RW
541         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
542             MemorySegment segment = MemorySegment.mapFile(f.toPath(), 0L, 0L, FileChannel.MapMode.READ_WRITE, scope);
543             assertEquals(segment.byteSize(), 0);
544             assertEquals(segment.isMapped(), true);
545             assertFalse(segment.isReadOnly());
546             segment.force();
547             segment.load();
548             segment.isLoaded();
549             segment.unload();
550         }

627     public void bufferProperties(ByteBuffer bb, Predicate<MemorySegment> _unused) {
628         MemorySegment segment = MemorySegment.ofByteBuffer(bb);
629         ByteBuffer buffer = segment.asByteBuffer();
630         assertEquals(buffer.position(), 0);
631         assertEquals(buffer.capacity(), segment.byteSize());
632         assertEquals(buffer.limit(), segment.byteSize());
633     }
634 
635     @Test
636     public void testRoundTripAccess() {
637         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
638             MemorySegment ms = MemorySegment.allocateNative(4, 1, scope);
639             MemorySegment msNoAccess = ms.asReadOnly();
640             MemorySegment msRoundTrip = MemorySegment.ofByteBuffer(msNoAccess.asByteBuffer());
641             assertEquals(msNoAccess.isReadOnly(), msRoundTrip.isReadOnly());
642         }
643     }
644 
645     @Test(expectedExceptions = IllegalStateException.class)
646     public void testDeadAccessOnClosedBufferSegment() {
647         MemorySegment s1 = MemorySegment.allocateNative(JAVA_INT, ResourceScope.newConfinedScope());
648         MemorySegment s2 = MemorySegment.ofByteBuffer(s1.asByteBuffer());
649 
650         // memory freed
651         s1.scope().close();
652 
653         s2.set(JAVA_INT, 0, 10); // Dead access!
654     }
655 
656     @Test(dataProvider = "allScopes")
657     public void testIOOnSegmentBuffer(Supplier<ResourceScope> scopeSupplier) throws IOException {
658         File tmp = File.createTempFile("tmp", "txt");
659         tmp.deleteOnExit();
660         ResourceScope scope;
661         try (FileChannel channel = FileChannel.open(tmp.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE) ;
662              ResourceScope scp = closeableScopeOrNull(scope = scopeSupplier.get())) {
663             MemorySegment segment = MemorySegment.allocateNative(10, 1, scope);
664             for (int i = 0; i < 10; i++) {
665                 segment.set(JAVA_BYTE, i, (byte) i);
666             }
667             ByteBuffer bb = segment.asByteBuffer();
668             assertEquals(channel.write(bb), 10);
669             segment.fill((byte)0x00);
670             assertEquals(bb.clear(), ByteBuffer.wrap(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}));
671             assertEquals(channel.position(0).read(bb.clear()), 10);
672             assertEquals(bb.flip(), ByteBuffer.wrap(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}));
673         }
674     }
675 
676     static final Class<IllegalStateException> ISE = IllegalStateException.class;
677 
678     @Test(dataProvider = "closeableScopes")
679     public void testIOOnClosedSegmentBuffer(Supplier<ResourceScope> scopeSupplier) throws IOException {
680         File tmp = File.createTempFile("tmp", "txt");
681         tmp.deleteOnExit();
682         try (FileChannel channel = FileChannel.open(tmp.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) {
683             MemorySegment segment = MemorySegment.allocateNative(10, scopeSupplier.get());
684             for (int i = 0; i < 10; i++) {
685                 segment.set(JAVA_BYTE, i, (byte) i);
686             }
687             ByteBuffer bb = segment.asByteBuffer();
688             segment.scope().close();
689             assertThrows(ISE, () -> channel.read(bb));
690             assertThrows(ISE, () -> channel.read(new ByteBuffer[] {bb}));
691             assertThrows(ISE, () -> channel.read(new ByteBuffer[] {bb}, 0, 1));
692             assertThrows(ISE, () -> channel.write(bb));
693             assertThrows(ISE, () -> channel.write(new ByteBuffer[] {bb}));
694             assertThrows(ISE, () -> channel.write(new ByteBuffer[] {bb}, 0 ,1));
695         }
696     }
697 
698     @Test
699     public void buffersAndArraysFromSlices() {
700         try (ResourceScope scope = ResourceScope.newSharedScope()) {
701             MemorySegment segment = MemorySegment.allocateNative(16, scope);
702             int newSize = 8;
703             var slice = segment.asSlice(4, newSize);
704 
705             var bytes = slice.toArray(JAVA_BYTE);
706             assertEquals(newSize, bytes.length);
707 
708             var buffer = slice.asByteBuffer();
709             // Fails for heap segments, but passes for native segments:
710             assertEquals(0, buffer.position());
711             assertEquals(newSize, buffer.limit());
712             assertEquals(newSize, buffer.capacity());
713         }
714     }
715 
716     @Test
717     public void viewsFromSharedSegment() {
718         try (ResourceScope scope = ResourceScope.newSharedScope()) {
719             MemorySegment segment = MemorySegment.allocateNative(16, scope);
720             var byteBuffer = segment.asByteBuffer();
721             byteBuffer.asReadOnlyBuffer();
722             byteBuffer.slice(0, 8);
723         }
724     }
725 
726     @DataProvider(name = "segments")
727     public static Object[][] segments() throws Throwable {
728         return new Object[][] {
729                 { (Supplier<MemorySegment>) () -> MemorySegment.allocateNative(16, ResourceScope.newImplicitScope()) },
730                 { (Supplier<MemorySegment>) () -> MemorySegment.allocateNative(16, ResourceScope.newConfinedScope()) },
731                 { (Supplier<MemorySegment>) () -> MemorySegment.ofArray(new byte[16]) }
732         };
733     }
734 
735     @DataProvider(name = "closeableScopes")
736     public static Object[][] closeableScopes() {
737         return new Object[][] {
738                 { (Supplier<ResourceScope>) () -> ResourceScope.newSharedScope()   },
739                 { (Supplier<ResourceScope>) () -> ResourceScope.newConfinedScope() },
740                 { (Supplier<ResourceScope>) () -> ResourceScope.newSharedScope(Cleaner.create())   },
741                 { (Supplier<ResourceScope>) () -> ResourceScope.newConfinedScope(Cleaner.create()) },
742                 { (Supplier<ResourceScope>) () -> ResourceScope.newImplicitScope() }







743         };
744     }
745 
746     @DataProvider(name = "allScopes")
747     public static Object[][] allScopes() {
748         return Stream.of(new Object[][] { { (Supplier<ResourceScope>)ResourceScope::globalScope } }, closeableScopes())
749                 .flatMap(Arrays::stream)
750                 .toArray(Object[][]::new);
751     }
752 
753     static ResourceScope closeableScopeOrNull(ResourceScope scope) {
754         if (scope == ResourceScope.globalScope())
755             return null;
756         return scope;
757     }
758 
759     @DataProvider(name = "bufferOps")
760     public static Object[][] bufferOps() throws Throwable {
761         List<Object[]> args = new ArrayList<>();
762         bufferOpsArgs(args, bb -> bb, ByteBuffer.class);
763         bufferOpsArgs(args, ByteBuffer::asCharBuffer, CharBuffer.class);
764         bufferOpsArgs(args, ByteBuffer::asShortBuffer, ShortBuffer.class);
765         bufferOpsArgs(args, ByteBuffer::asIntBuffer, IntBuffer.class);
766         bufferOpsArgs(args, ByteBuffer::asFloatBuffer, FloatBuffer.class);
767         bufferOpsArgs(args, ByteBuffer::asLongBuffer, LongBuffer.class);
768         bufferOpsArgs(args, ByteBuffer::asDoubleBuffer, DoubleBuffer.class);
769         return args.toArray(Object[][]::new);
770     }
771 
772     static void bufferOpsArgs(List<Object[]> argsList, Function<ByteBuffer, Buffer> factory, Class<?> bufferClass) {
773         for (Method m : bufferClass.getMethods()) {
774             //skip statics and method declared in j.l.Object

797 
798     static Map<MethodHandle, Object[]> varHandleMembers(ByteBuffer bb, VarHandle handle) {
799         Map<MethodHandle, Object[]> members = new HashMap<>();
800         for (VarHandle.AccessMode mode : VarHandle.AccessMode.values()) {
801             Class<?>[] params = handle.accessModeType(mode).parameterArray();
802             Object[] args = Stream.concat(Stream.of(bb), Stream.of(params).skip(1)
803                     .map(TestByteBuffer::defaultValue))
804                     .toArray();
805             try {
806                 members.put(MethodHandles.varHandleInvoker(mode, handle.accessModeType(mode)), args);
807             } catch (Throwable ex) {
808                 throw new AssertionError(ex);
809             }
810         }
811         return members;
812     }
813 
814     @DataProvider(name = "resizeOps")
815     public Object[][] resizeOps() {
816         Consumer<MemorySegment> byteInitializer =
817                 (base) -> initBytes(base, bytes, (addr, pos) -> addr.set(JAVA_BYTE, pos, (byte)(long)pos));
818         Consumer<MemorySegment> charInitializer =
819                 (base) -> initBytes(base, chars, (addr, pos) -> addr.setAtIndex(JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), pos, (char)(long)pos));
820         Consumer<MemorySegment> shortInitializer =
821                 (base) -> initBytes(base, shorts, (addr, pos) -> addr.setAtIndex(JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), pos, (short)(long)pos));
822         Consumer<MemorySegment> intInitializer =
823                 (base) -> initBytes(base, ints, (addr, pos) -> addr.setAtIndex(JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), pos, (int)(long)pos));
824         Consumer<MemorySegment> floatInitializer =
825                 (base) -> initBytes(base, floats, (addr, pos) -> addr.setAtIndex(JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), pos, (float)(long)pos));
826         Consumer<MemorySegment> longInitializer =
827                 (base) -> initBytes(base, longs, (addr, pos) -> addr.setAtIndex(JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), pos, (long)pos));
828         Consumer<MemorySegment> doubleInitializer =
829                 (base) -> initBytes(base, doubles, (addr, pos) -> addr.setAtIndex(JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), pos, (double)(long)pos));
830 
831         Consumer<MemorySegment> byteChecker =
832                 (base) -> checkBytes(base, bytes, Function.identity(), (addr, pos) -> addr.get(JAVA_BYTE, pos), ByteBuffer::get);
833         Consumer<MemorySegment> charChecker =
834                 (base) -> checkBytes(base, chars, ByteBuffer::asCharBuffer, (addr, pos) -> addr.getAtIndex(JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), pos), CharBuffer::get);
835         Consumer<MemorySegment> shortChecker =
836                 (base) -> checkBytes(base, shorts, ByteBuffer::asShortBuffer, (addr, pos) -> addr.getAtIndex(JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), pos), ShortBuffer::get);
837         Consumer<MemorySegment> intChecker =
838                 (base) -> checkBytes(base, ints, ByteBuffer::asIntBuffer, (addr, pos) -> addr.getAtIndex(JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), pos), IntBuffer::get);
839         Consumer<MemorySegment> floatChecker =
840                 (base) -> checkBytes(base, floats, ByteBuffer::asFloatBuffer, (addr, pos) -> addr.getAtIndex(JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), pos), FloatBuffer::get);
841         Consumer<MemorySegment> longChecker =
842                 (base) -> checkBytes(base, longs, ByteBuffer::asLongBuffer, (addr, pos) -> addr.getAtIndex(JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), pos), LongBuffer::get);
843         Consumer<MemorySegment> doubleChecker =
844                 (base) -> checkBytes(base, doubles, ByteBuffer::asDoubleBuffer, (addr, pos) -> addr.getAtIndex(JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), pos), DoubleBuffer::get);
845 
846         return new Object[][]{
847                 {byteChecker, byteInitializer, bytes},
848                 {charChecker, charInitializer, chars},
849                 {shortChecker, shortInitializer, shorts},
850                 {intChecker, intInitializer, ints},
851                 {floatChecker, floatInitializer, floats},
852                 {longChecker, longInitializer, longs},
853                 {doubleChecker, doubleInitializer, doubles}
854         };
855     }
856 
857     static Object defaultValue(Class<?> c) {
858         if (c.isPrimitive()) {
859             if (c == char.class) {
860                 return (char)0;
861             } else if (c == boolean.class) {
862                 return false;
863             } else if (c == byte.class) {
864                 return (byte)0;
< prev index next >