/* * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ import java.nio.ByteBuffer; import java.util.concurrent.atomic.AtomicReference; import jdk.internal.misc.Unsafe; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; /* * @test * @bug 8299684 * @summary Unit test for the JNI function NewDirectByteBuffer * @requires (sun.arch.data.model == "64" & os.maxMemory >= 8g) * @modules java.base/jdk.internal.misc * @run junit/othervm/native NewDirectByteBuffer */ public class NewDirectByteBuffer { private static final Unsafe UNSAFE; static { System.loadLibrary("NewDirectByteBuffer"); UNSAFE = Unsafe.getUnsafe(); } private static final void checkBuffer(ByteBuffer buf, long capacity) { // Verify that the JNI function returns the correct capacity assertEquals(capacity, getDirectByteBufferCapacity(buf), "GetDirectBufferCapacity returned unexpected value"); // Verify that the initial state values are correct assertTrue(buf.isDirect(), "Buffer is not direct"); assertFalse(buf.hasArray(), "Buffer has an array"); if (capacity > 0) { assertTrue(buf.hasRemaining(), "Buffer has no remaining values"); } assertFalse(buf.isReadOnly(), "Buffer s read-only"); assertEquals(capacity, buf.capacity(), "Buffer::capacity returned unexpected value"); assertEquals(0L, buf.position(), "Buffer::position returned unexpected value"); assertEquals(capacity, buf.limit(), "Buffer::limit returned unexpected value"); // Verify that the various state mutators work correctly int halfPos = buf.capacity()/2; buf.position(halfPos); assertEquals(halfPos, buf.position(), "Position not set to halfPos"); assertEquals(buf.capacity() - halfPos, buf.remaining(), "Remaining not capacity - halfPos"); buf.mark(); int twoThirdsPos = 2*(buf.capacity()/3); buf.position(twoThirdsPos); assertEquals(twoThirdsPos, buf.position(), "Position not set to twoThirdsPos"); assertEquals(buf.capacity() - twoThirdsPos, buf.remaining(), "Remaining != capacity - twoThirdsPos"); buf.reset(); assertEquals(halfPos, buf.position(), "Buffer not reset to halfPos"); buf.limit(twoThirdsPos); assertEquals(twoThirdsPos, buf.limit(), "Limit not set to twoThirdsPos"); assertEquals(twoThirdsPos - halfPos, buf.remaining(), "Remaining != twoThirdsPos - halfPos"); buf.position(twoThirdsPos); assertFalse(buf.hasRemaining(), "Buffer has remaining values"); } @ParameterizedTest @ValueSource(longs = {0L, 1L, (long)Integer.MAX_VALUE/2, (long)Integer.MAX_VALUE - 1, (long)Integer.MAX_VALUE}) void legalCapacities(long capacity) { long addr; try { addr = UNSAFE.allocateMemory(capacity); } catch (OutOfMemoryError ignore) { System.err.println("legalCapacities( " + capacity + ") test skipped due to insufficient memory"); return; } try { ByteBuffer buf = newDirectByteBuffer(addr, capacity); assertEquals(addr, getDirectBufferAddress(buf), "GetDirectBufferAddress does not return supplied address"); checkBuffer(buf, capacity); } finally { UNSAFE.freeMemory(addr); } } @ParameterizedTest @ValueSource(longs = {Long.MIN_VALUE, (long)Integer.MIN_VALUE - 1L, -1L, (long)Integer.MAX_VALUE + 1L, 3_000_000_000L, 5_000_000_000L, Long.MAX_VALUE}) void illegalCapacities(long capacity) { assertThrows(IllegalArgumentException.class, () -> { long addr = UNSAFE.allocateMemory(1); try { ByteBuffer buf = newDirectByteBuffer(addr, capacity); } finally { UNSAFE.freeMemory(addr); } }); } // See libNewDirectByteBuffer.c for implementations. private static native ByteBuffer newDirectByteBuffer(long addr, long capacity); private static native long getDirectByteBufferCapacity(ByteBuffer buf); private static native long getDirectBufferAddress(ByteBuffer buf); }