/*
 * Copyright (c) 2000, 2024, 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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.
 */

package java.nio;

import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.access.foreign.MappedMemoryUtilsProxy;
import jdk.internal.access.foreign.UnmapperProxy;
import jdk.internal.foreign.AbstractMemorySegmentImpl;
import jdk.internal.foreign.MemorySessionImpl;
import jdk.internal.misc.ScopedMemoryAccess;
import jdk.internal.misc.Unsafe;
import jdk.internal.misc.VM.BufferPool;
import jdk.internal.util.Preconditions;
import jdk.internal.vm.annotation.ForceInline;

import java.lang.foreign.MemorySegment;
import java.lang.ref.Reference;
import java.util.List;
import java.util.Spliterator;
import java.util.function.BiFunction;
import java.util.function.Function;

/**
 * A container for data of a specific primitive type.
 *
 * <p> A buffer is a linear, finite sequence of elements of a specific
 * primitive type.  Aside from its content, the essential properties of a
 * buffer are its capacity, limit, and position: </p>
 *
 * <blockquote>
 *
 *   <p> A buffer's <i>capacity</i> is the number of elements it contains.  The
 *   capacity of a buffer is never negative and never changes.  </p>
 *
 *   <p> A buffer's <i>limit</i> is the index of the first element that should
 *   not be read or written.  A buffer's limit is never negative and is never
 *   greater than its capacity.  </p>
 *
 *   <p> A buffer's <i>position</i> is the index of the next element to be
 *   read or written.  A buffer's position is never negative and is never
 *   greater than its limit.  </p>
 *
 * </blockquote>
 *
 * <p> There is one subclass of this class for each non-boolean primitive type.
 *
 *
 * <h2> Transferring data </h2>
 *
 * <p> Each subclass of this class defines two categories of <i>get</i> and
 * <i>put</i> operations: </p>
 *
 * <blockquote>
 *
 *   <p> <i>Relative</i> operations read or write one or more elements starting
 *   at the current position and then increment the position by the number of
 *   elements transferred.  If the requested transfer exceeds the limit then a
 *   relative <i>get</i> operation throws a {@link BufferUnderflowException}
 *   and a relative <i>put</i> operation throws a {@link
 *   BufferOverflowException}; in either case, no data is transferred.  </p>
 *
 *   <p> <i>Absolute</i> operations take an explicit element index and do not
 *   affect the position.  Absolute <i>get</i> and <i>put</i> operations throw
 *   an {@link IndexOutOfBoundsException} if the index argument exceeds the
 *   limit.  </p>
 *
 * </blockquote>
 *
 * <p> Data may also, of course, be transferred in to or out of a buffer by the
 * I/O operations of an appropriate channel, which are always relative to the
 * current position.
 *
 *
 * <h2> Marking and resetting </h2>
 *
 * <p> A buffer's <i>mark</i> is the index to which its position will be reset
 * when the {@link #reset reset} method is invoked.  The mark is not always
 * defined, but when it is defined it is never negative and is never greater
 * than the position.  If the mark is defined then it is discarded when the
 * position or the limit is adjusted to a value smaller than the mark.  If the
 * mark is not defined then invoking the {@link #reset reset} method causes an
 * {@link InvalidMarkException} to be thrown.
 *
 *
 * <h2> Invariants </h2>
 *
 * <p> The following invariant holds for the mark, position, limit, and
 * capacity values:
 *
 * <blockquote>
 *     {@code 0} {@code <=}
 *     <i>mark</i> {@code <=}
 *     <i>position</i> {@code <=}
 *     <i>limit</i> {@code <=}
 *     <i>capacity</i>
 * </blockquote>
 *
 * <p> A newly-created buffer always has a position of zero and a mark that is
 * undefined.  The initial limit may be zero, or it may be some other value
 * that depends upon the type of the buffer and the manner in which it is
 * constructed.  Each element of a newly-allocated buffer is initialized
 * to zero.
 *
 *
 * <h2> Additional operations </h2>
 *
 * <p> In addition to methods for accessing the position, limit, and capacity
 * values and for marking and resetting, this class also defines the following
 * operations upon buffers:
 *
 * <ul>
 *
 *   <li><p> {@link #clear} makes a buffer ready for a new sequence of
 *   channel-read or relative <i>put</i> operations: It sets the limit to the
 *   capacity and the position to zero.  </p></li>
 *
 *   <li><p> {@link #flip} makes a buffer ready for a new sequence of
 *   channel-write or relative <i>get</i> operations: It sets the limit to the
 *   current position and then sets the position to zero.  </p></li>
 *
 *   <li><p> {@link #rewind} makes a buffer ready for re-reading the data that
 *   it already contains: It leaves the limit unchanged and sets the position
 *   to zero.  </p></li>
 *
 *   <li><p> The {@link #slice} and {@link #slice(int,int) slice(index,length)}
 *   methods create a subsequence of a buffer: They leave the limit and the
 *   position unchanged. </p></li>
 *
 *   <li><p> {@link #duplicate} creates a shallow copy of a buffer: It leaves
 *   the limit and the position unchanged. </p></li>
 *
 * </ul>
 *
 *
 * <h2> Read-only buffers </h2>
 *
 * <p> Every buffer is readable, but not every buffer is writable.  The
 * mutation methods of each buffer class are specified as <i>optional
 * operations</i> that will throw a {@link ReadOnlyBufferException} when
 * invoked upon a read-only buffer.  A read-only buffer does not allow its
 * content to be changed, but its mark, position, and limit values are mutable.
 * Whether or not a buffer is read-only may be determined by invoking its
 * {@link #isReadOnly isReadOnly} method.
 *
 *
 * <h2> Thread safety </h2>
 *
 * <p> Buffers are not safe for use by multiple concurrent threads.  If a
 * buffer is to be used by more than one thread then access to the buffer
 * should be controlled by appropriate synchronization.
 *
 *
 * <h2> Invocation chaining </h2>
 *
 * <p> Methods in this class that do not otherwise have a value to return are
 * specified to return the buffer upon which they are invoked.  This allows
 * method invocations to be chained; for example, the sequence of statements
 *
 * {@snippet lang=java :
 *     b.flip();
 *     b.position(23);
 *     b.limit(42);
 * }
 *
 * can be replaced by the single, more compact statement
 *
 * {@snippet lang=java :
 *     b.flip().position(23).limit(42);
 * }
 *
 *
 * @author Mark Reinhold
 * @author JSR-51 Expert Group
 * @since 1.4
 * @sealedGraph
 */

public abstract sealed class Buffer
    permits ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer,
        LongBuffer, ShortBuffer {
    // Cached unsafe-access object
    static final Unsafe UNSAFE = Unsafe.getUnsafe();

    static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();

    /**
     * The characteristics of Spliterators that traverse and split elements
     * maintained in Buffers.
     */
    static final int SPLITERATOR_CHARACTERISTICS =
        Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED;

    // Invariants: mark <= position <= limit <= capacity
    private int mark = -1;
    private int position = 0;
    private int limit;
    private final int capacity;

    // Used by heap byte buffers or direct buffers with Unsafe access
    // For heap byte buffers this field will be the address relative to the
    // array base address and offset into that array. The address might
    // not align on a word boundary for slices, nor align at a long word
    // (8 byte) boundary for byte[] allocations on 32-bit systems.
    // For direct buffers it is the start address of the memory region. The
    // address might not align on a word boundary for slices, nor when created
    // using JNI, see NewDirectByteBuffer(void*, long).
    // Should ideally be declared final
    // NOTE: hoisted here for speed in JNI GetDirectBufferAddress
    long address;

    // Used by buffers generated by the memory access API (JEP-370)
    final MemorySegment segment;


    // Creates a new buffer with given address and capacity.
    //
    Buffer(long addr, int cap, MemorySegment segment) {
        this.address = addr;
        this.capacity = cap;
        this.segment = segment;
    }

    // Creates a new buffer with the given mark, position, limit, and capacity,
    // after checking invariants.
    //
    Buffer(int mark, int pos, int lim, int cap, MemorySegment segment) {       // package-private
        if (cap < 0)
            throw createCapacityException(cap);
        this.capacity = cap;
        this.segment = segment;
        limit(lim);
        position(pos);
        if (mark >= 0) {
            if (mark > pos)
                throw new IllegalArgumentException("mark > position: ("
                                                   + mark + " > " + pos + ")");
            this.mark = mark;
        }
    }

    /**
     * Returns an {@code IllegalArgumentException} indicating that the source
     * and target are the same {@code Buffer}.  Intended for use in
     * {@code put(src)} when the parameter is the {@code Buffer} on which the
     * method is being invoked.
     *
     * @return  IllegalArgumentException
     *          With a message indicating equal source and target buffers
     */
    static IllegalArgumentException createSameBufferException() {
        return new IllegalArgumentException("The source buffer is this buffer");
    }

    /**
     * Verify that the capacity is nonnegative.
     *
     * @param  capacity
     *         The new buffer's capacity, in $type$s
     *
     * @throws IllegalArgumentException
     *         If the {@code capacity} is a negative integer
     */
    static IllegalArgumentException createCapacityException(int capacity) {
        assert capacity < 0 : "capacity expected to be negative";
        return new IllegalArgumentException("capacity < 0: ("
            + capacity + " < 0)");
    }

    /**
     * Returns this buffer's capacity.
     *
     * @return  The capacity of this buffer
     */
    public final int capacity() {
        return capacity;
    }

    /**
     * Returns this buffer's position.
     *
     * @return  The position of this buffer
     */
    public final int position() {
        return position;
    }

    /**
     * Sets this buffer's position.  If the mark is defined and larger than the
     * new position then it is discarded.
     *
     * @param  newPosition
     *         The new position value; must be non-negative
     *         and no larger than the current limit
     *
     * @return  This buffer
     *
     * @throws  IllegalArgumentException
     *          If the preconditions on {@code newPosition} do not hold
     */
    public Buffer position(int newPosition) {
        if (newPosition > limit | newPosition < 0)
            throw createPositionException(newPosition);
        if (mark > newPosition) mark = -1;
        position = newPosition;
        return this;
    }

    /**
     * Verify that {@code 0 < newPosition <= limit}
     *
     * @param newPosition
     *        The new position value
     *
     * @throws IllegalArgumentException
     *         If the specified position is out of bounds.
     */
    private IllegalArgumentException createPositionException(int newPosition) {
        String msg = null;

        if (newPosition > limit) {
            msg = "newPosition > limit: (" + newPosition + " > " + limit + ")";
        } else { // assume negative
            assert newPosition < 0 : "newPosition expected to be negative";
            msg = "newPosition < 0: (" + newPosition + " < 0)";
        }

        return new IllegalArgumentException(msg);
    }

    /**
     * Returns this buffer's limit.
     *
     * @return  The limit of this buffer
     */
    public final int limit() {
        return limit;
    }

    /**
     * Sets this buffer's limit.  If the position is larger than the new limit
     * then it is set to the new limit.  If the mark is defined and larger than
     * the new limit then it is discarded.
     *
     * @param  newLimit
     *         The new limit value; must be non-negative
     *         and no larger than this buffer's capacity
     *
     * @return  This buffer
     *
     * @throws  IllegalArgumentException
     *          If the preconditions on {@code newLimit} do not hold
     */
    public Buffer limit(int newLimit) {
        if (newLimit > capacity | newLimit < 0)
            throw createLimitException(newLimit);
        limit = newLimit;
        if (position > newLimit) position = newLimit;
        if (mark > newLimit) mark = -1;
        return this;
    }

    /**
     * Verify that {@code 0 < newLimit <= capacity}
     *
     * @param newLimit
     *        The new limit value
     *
     * @throws IllegalArgumentException
     *         If the specified limit is out of bounds.
     */
    private IllegalArgumentException createLimitException(int newLimit) {
        String msg = null;

        if (newLimit > capacity) {
            msg = "newLimit > capacity: (" + newLimit + " > " + capacity + ")";
        } else { // assume negative
            assert newLimit < 0 : "newLimit expected to be negative";
            msg = "newLimit < 0: (" + newLimit + " < 0)";
        }

        return new IllegalArgumentException(msg);
    }

    /**
     * Sets this buffer's mark at its position.
     *
     * @return  This buffer
     */
    public Buffer mark() {
        mark = position;
        return this;
    }

    /**
     * Resets this buffer's position to the previously-marked position.
     *
     * <p> Invoking this method neither changes nor discards the mark's
     * value. </p>
     *
     * @return  This buffer
     *
     * @throws  InvalidMarkException
     *          If the mark has not been set
     */
    public Buffer reset() {
        int m = mark;
        if (m < 0)
            throw new InvalidMarkException();
        position = m;
        return this;
    }

    /**
     * Clears this buffer.  The position is set to zero, the limit is set to
     * the capacity, and the mark is discarded.
     *
     * <p> Invoke this method before using a sequence of channel-read or
     * <i>put</i> operations to fill this buffer.  For example:
     *
     * {@snippet lang=java :
     *     buf.clear();     // Prepare buffer for reading
     *     in.read(buf);    // Read data
     * }
     *
     * <p> This method does not actually erase the data in the buffer, but it
     * is named as if it did because it will most often be used in situations
     * in which that might as well be the case. </p>
     *
     * @return  This buffer
     */
    public Buffer clear() {
        position = 0;
        limit = capacity;
        mark = -1;
        return this;
    }

    /**
     * Flips this buffer.  The limit is set to the current position and then
     * the position is set to zero.  If the mark is defined then it is
     * discarded.
     *
     * <p> After a sequence of channel-read or <i>put</i> operations, invoke
     * this method to prepare for a sequence of channel-write or relative
     * <i>get</i> operations.  For example:
     *
     * {@snippet lang=java :
     *     buf.put(magic);    // Prepend header
     *     in.read(buf);      // Read data into rest of buffer
     *     buf.flip();        // Flip buffer
     *     out.write(buf);    // Write header + data to channel
     * }
     *
     * <p> This method is often used in conjunction with the {@link
     * java.nio.ByteBuffer#compact compact} method when transferring data from
     * one place to another.  </p>
     *
     * @return  This buffer
     */
    public Buffer flip() {
        limit = position;
        position = 0;
        mark = -1;
        return this;
    }

    /**
     * Rewinds this buffer.  The position is set to zero and the mark is
     * discarded.
     *
     * <p> Invoke this method before a sequence of channel-write or <i>get</i>
     * operations, assuming that the limit has already been set
     * appropriately.  For example:
     *
     * {@snippet lang=java :
     *     out.write(buf);    // Write remaining data
     *     buf.rewind();      // Rewind buffer
     *     buf.get(array);    // Copy data into array
     * }
     *
     * @return  This buffer
     */
    public Buffer rewind() {
        position = 0;
        mark = -1;
        return this;
    }

    /**
     * Returns the number of elements between the current position and the
     * limit.
     *
     * @return  The number of elements remaining in this buffer
     */
    public final int remaining() {
        int rem = limit - position;
        return rem > 0 ? rem : 0;
    }

    /**
     * Tells whether there are any elements between the current position and
     * the limit.
     *
     * @return  {@code true} if, and only if, there is at least one element
     *          remaining in this buffer
     */
    public final boolean hasRemaining() {
        return position < limit;
    }

    /**
     * Tells whether or not this buffer is read-only.
     *
     * @return  {@code true} if, and only if, this buffer is read-only
     */
    public abstract boolean isReadOnly();

    /**
     * Tells whether or not this buffer is backed by an accessible
     * array.
     *
     * <p> If this method returns {@code true} then the {@link #array() array}
     * and {@link #arrayOffset() arrayOffset} methods may safely be invoked.
     * </p>
     *
     * @return  {@code true} if, and only if, this buffer
     *          is backed by an array and is not read-only
     *
     * @since 1.6
     */
    public abstract boolean hasArray();

    /**
     * Returns the array that backs this
     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
     *
     * <p> This method is intended to allow array-backed buffers to be
     * passed to native code more efficiently. Concrete subclasses
     * provide more strongly-typed return values for this method.
     *
     * <p> Modifications to this buffer's content will cause the returned
     * array's content to be modified, and vice versa.
     *
     * <p> Invoke the {@link #hasArray hasArray} method before invoking this
     * method in order to ensure that this buffer has an accessible backing
     * array.  </p>
     *
     * @return  The array that backs this buffer
     *
     * @throws  ReadOnlyBufferException
     *          If this buffer is backed by an array but is read-only
     *
     * @throws  UnsupportedOperationException
     *          If this buffer is not backed by an accessible array
     *
     * @since 1.6
     */
    public abstract Object array();

    /**
     * Returns the offset within this buffer's backing array of the first
     * element of the buffer&nbsp;&nbsp;<i>(optional operation)</i>.
     *
     * <p> If this buffer is backed by an array then buffer position <i>p</i>
     * corresponds to array index <i>p</i>&nbsp;+&nbsp;{@code arrayOffset()}.
     *
     * <p> Invoke the {@link #hasArray hasArray} method before invoking this
     * method in order to ensure that this buffer has an accessible backing
     * array.  </p>
     *
     * @return  The offset within this buffer's array
     *          of the first element of the buffer
     *
     * @throws  ReadOnlyBufferException
     *          If this buffer is backed by an array but is read-only
     *
     * @throws  UnsupportedOperationException
     *          If this buffer is not backed by an accessible array
     *
     * @since 1.6
     */
    public abstract int arrayOffset();

    /**
     * Tells whether or not this buffer is
     * <a href="ByteBuffer.html#direct"><i>direct</i></a>.
     *
     * @return  {@code true} if, and only if, this buffer is direct
     *
     * @since 1.6
     */
    public abstract boolean isDirect();

    /**
     * Creates a new buffer whose content is a shared subsequence of
     * this buffer's content.
     *
     * <p> The content of the new buffer will start at this buffer's current
     * position.  Changes to this buffer's content will be visible in the new
     * buffer, and vice versa; the two buffers' position, limit, and mark
     * values will be independent.
     *
     * <p> The new buffer's position will be zero, its capacity and its limit
     * will be the number of elements remaining in this buffer, its mark will be
     * undefined. The new buffer will be direct if, and only if, this buffer is
     * direct, and it will be read-only if, and only if, this buffer is
     * read-only.  </p>
     *
     * @return  The new buffer
     *
     * @since 9
     */
    public abstract Buffer slice();

    /**
     * Creates a new buffer whose content is a shared subsequence of
     * this buffer's content.
     *
     * <p> The content of the new buffer will start at position {@code index}
     * in this buffer, and will contain {@code length} elements. Changes to
     * this buffer's content will be visible in the new buffer, and vice versa;
     * the two buffers' position, limit, and mark values will be independent.
     *
     * <p> The new buffer's position will be zero, its capacity and its limit
     * will be {@code length}, its mark will be undefined. The new buffer will
     * be direct if, and only if, this buffer is direct, and it will be
     * read-only if, and only if, this buffer is read-only.  </p>
     *
     * @param   index
     *          The position in this buffer at which the content of the new
     *          buffer will start; must be non-negative and no larger than
     *          {@link #limit() limit()}
     *
     * @param   length
     *          The number of elements the new buffer will contain; must be
     *          non-negative and no larger than {@code limit() - index}
     *
     * @return  The new buffer
     *
     * @throws  IndexOutOfBoundsException
     *          If {@code index} is negative or greater than {@code limit()},
     *          {@code length} is negative, or {@code length > limit() - index}
     *
     * @since 13
     */
    public abstract Buffer slice(int index, int length);

    /**
     * Creates a new buffer that shares this buffer's content.
     *
     * <p> The content of the new buffer will be that of this buffer.  Changes
     * to this buffer's content will be visible in the new buffer, and vice
     * versa; the two buffers' position, limit, and mark values will be
     * independent.
     *
     * <p> The new buffer's capacity, limit, position and mark values will be
     * identical to those of this buffer. The new buffer will be direct if, and
     * only if, this buffer is direct, and it will be read-only if, and only if,
     * this buffer is read-only.  </p>
     *
     * @return  The new buffer
     *
     * @since 9
     */
    public abstract Buffer duplicate();


    // -- Package-private methods for bounds checking, etc. --

    /**
     *
     * @return the base reference, paired with the address
     * field, which in combination can be used for unsafe access into a heap
     * buffer or direct byte buffer (and views of).
     */
    abstract Object base();

    /**
     * Checks the current position against the limit, throwing a {@link
     * BufferUnderflowException} if it is not smaller than the limit, and then
     * increments the position.
     *
     * @return  The current position value, before it is incremented
     */
    final int nextGetIndex() {                          // package-private
        int p = position;
        if (p >= limit)
            throw new BufferUnderflowException();
        position = p + 1;
        return p;
    }

    final int nextGetIndex(int nb) {                    // package-private
        int p = position;
        if (limit - p < nb)
            throw new BufferUnderflowException();
        position = p + nb;
        return p;
    }

    /**
     * Checks the current position against the limit, throwing a {@link
     * BufferOverflowException} if it is not smaller than the limit, and then
     * increments the position.
     *
     * @return  The current position value, before it is incremented
     */
    final int nextPutIndex() {                          // package-private
        int p = position;
        if (p >= limit)
            throw new BufferOverflowException();
        position = p + 1;
        return p;
    }

    final int nextPutIndex(int nb) {                    // package-private
        int p = position;
        if (limit - p < nb)
            throw new BufferOverflowException();
        position = p + nb;
        return p;
    }

    /**
     * Exception formatter that returns an {@link IndexOutOfBoundsException}
     * with no detail message.
     */
    private static final BiFunction<String,List<Number>,IndexOutOfBoundsException>
        IOOBE_FORMATTER = Preconditions.outOfBoundsExceptionFormatter(new Function<>() {
        @Override
        public IndexOutOfBoundsException apply(String s) {
            return new IndexOutOfBoundsException();
        }
    });

    /**
     * Checks the given index against the limit, throwing an {@link
     * IndexOutOfBoundsException} if it is greater than the limit
     * or is negative.
     */
    @ForceInline
    final int checkIndex(int i) {                       // package-private
        return Preconditions.checkIndex(i, limit, IOOBE_FORMATTER);
    }

    /**
     * Checks the given index and number of bytes against the range
     * {@code [0, limit]}, throwing an {@link
     * IndexOutOfBoundsException} if the index is negative or the index
     * plus the number of bytes is greater than the limit.
     */
    @ForceInline
    final int checkIndex(int i, int nb) {               // package-private
        return Preconditions.checkIndex(i, limit - nb + 1, IOOBE_FORMATTER);
    }

    /**
     * {@return the scale shifts for this Buffer}
     * <p>
     * The scale shifts are:
     *   ByteBuffer:               0
     *   ShortBuffer, CharBuffer:  1
     *   IntBuffer, FloatBuffer:   2
     *   LongBuffer, DoubleBuffer: 3
     */
    abstract int scaleShifts();

    abstract AbstractMemorySegmentImpl heapSegment(Object base,
                                                   long offset,
                                                   long length,
                                                   boolean readOnly,
                                                   MemorySessionImpl bufferScope);

    final int markValue() {                             // package-private
        return mark;
    }

    final void discardMark() {                          // package-private
        mark = -1;
    }

    @ForceInline
    final MemorySessionImpl session() {
        if (segment != null) {
            return ((AbstractMemorySegmentImpl)segment).sessionImpl();
        } else {
            return null;
        }
    }

    final void checkSession() {
        MemorySessionImpl session = session();
        if (session != null) {
            session.checkValidState();
        }
    }

    static {

        // setup access to this package in SharedSecrets
        SharedSecrets.setJavaNioAccess(
            new JavaNioAccess() {

                @Override
                public BufferPool getDirectBufferPool() {
                    return Bits.BUFFER_POOL;
                }

                @Override
                public ByteBuffer newDirectByteBuffer(long addr, int cap, Object obj, MemorySegment segment) {
                    return new DirectByteBuffer(addr, cap, obj, segment);
                }

                @Override
                public ByteBuffer newMappedByteBuffer(UnmapperProxy unmapperProxy, long address, int cap, Object obj, MemorySegment segment) {
                    return unmapperProxy == null
                            ? new DirectByteBuffer(address, cap, obj, segment)
                            : new DirectByteBuffer(address, cap, obj, unmapperProxy.fileDescriptor(), unmapperProxy.isSync(), segment);
                }

                @Override
                public ByteBuffer newHeapByteBuffer(byte[] hb, int offset, int capacity, MemorySegment segment) {
                    return new HeapByteBuffer(hb, -1, 0, capacity, capacity, offset, segment);
                }

                @Override
                public ByteBuffer newDirectByteBuffer(long addr, int cap) {
                    return new DirectByteBuffer(addr, cap);
                }

                @ForceInline
                @Override
                public Object getBufferBase(Buffer buffer) {
                    return buffer.base();
                }

                @Override
                public long getBufferAddress(Buffer buffer) {
                    return buffer.address;
                }

                @Override
                public UnmapperProxy unmapper(Buffer buffer) {
                    if (buffer instanceof MappedByteBuffer mbb) {
                        return mbb.unmapper();
                    } else {
                        return null;
                    }
                }

                @Override
                public MemorySegment bufferSegment(Buffer buffer) {
                    return buffer.segment;
                }

                @Override
                public void acquireSession(Buffer buffer) {
                    var scope = buffer.session();
                    if (scope != null) {
                        scope.acquire0();
                    }
                }

                @Override
                public void releaseSession(Buffer buffer) {
                    try {
                        var scope = buffer.session();
                        if (scope != null) {
                            scope.release0();
                        }
                    } finally {
                        Reference.reachabilityFence(buffer);
                    }
                }

                @Override
                public boolean isThreadConfined(Buffer buffer) {
                    var scope = buffer.session();
                    return scope != null && scope.ownerThread() != null;
                }

                @Override
                public boolean hasSession(Buffer buffer) {
                    return buffer.session() != null;
                }

                @Override
                public MappedMemoryUtilsProxy mappedMemoryUtils() {
                    return MappedMemoryUtils.PROXY;
                }

                @Override
                public void reserveMemory(long size, long cap) {
                    Bits.reserveMemory(size, cap);
                }

                @Override
                public void unreserveMemory(long size, long cap) {
                    Bits.unreserveMemory(size, cap);
                }

                @Override
                public int pageSize() {
                    return Bits.pageSize();
                }

                @ForceInline
                @Override
                public int scaleShifts(Buffer buffer) {
                    return buffer.scaleShifts();
                }

                @ForceInline
                @Override
                public AbstractMemorySegmentImpl heapSegment(Buffer buffer,
                                                             Object base,
                                                             long offset,
                                                             long length,
                                                             boolean readOnly,
                                                             MemorySessionImpl bufferScope) {
                    return buffer.heapSegment(base, offset, length, readOnly, bufferScope);
                }
            });
    }

}
