1 /*
  2  * Copyright (c) 2000, 2021, 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.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package java.nio;
 27 
 28 import jdk.internal.access.JavaNioAccess;
 29 import jdk.internal.access.SharedSecrets;
 30 import jdk.internal.access.foreign.MemorySegmentProxy;
 31 import jdk.internal.access.foreign.UnmapperProxy;
 32 import jdk.internal.misc.ScopedMemoryAccess;
 33 import jdk.internal.misc.ScopedMemoryAccess.Scope;
 34 import jdk.internal.misc.Unsafe;
 35 import jdk.internal.misc.VM.BufferPool;
 36 import jdk.internal.vm.annotation.ForceInline;
 37 
 38 import java.io.FileDescriptor;
 39 import java.util.Objects;
 40 import java.util.Spliterator;
 41 
 42 /**
 43  * A container for data of a specific primitive type.
 44  *
 45  * <p> A buffer is a linear, finite sequence of elements of a specific
 46  * primitive type.  Aside from its content, the essential properties of a
 47  * buffer are its capacity, limit, and position: </p>
 48  *
 49  * <blockquote>
 50  *
 51  *   <p> A buffer's <i>capacity</i> is the number of elements it contains.  The
 52  *   capacity of a buffer is never negative and never changes.  </p>
 53  *
 54  *   <p> A buffer's <i>limit</i> is the index of the first element that should
 55  *   not be read or written.  A buffer's limit is never negative and is never
 56  *   greater than its capacity.  </p>
 57  *
 58  *   <p> A buffer's <i>position</i> is the index of the next element to be
 59  *   read or written.  A buffer's position is never negative and is never
 60  *   greater than its limit.  </p>
 61  *
 62  * </blockquote>
 63  *
 64  * <p> There is one subclass of this class for each non-boolean primitive type.
 65  *
 66  *
 67  * <h2> Transferring data </h2>
 68  *
 69  * <p> Each subclass of this class defines two categories of <i>get</i> and
 70  * <i>put</i> operations: </p>
 71  *
 72  * <blockquote>
 73  *
 74  *   <p> <i>Relative</i> operations read or write one or more elements starting
 75  *   at the current position and then increment the position by the number of
 76  *   elements transferred.  If the requested transfer exceeds the limit then a
 77  *   relative <i>get</i> operation throws a {@link BufferUnderflowException}
 78  *   and a relative <i>put</i> operation throws a {@link
 79  *   BufferOverflowException}; in either case, no data is transferred.  </p>
 80  *
 81  *   <p> <i>Absolute</i> operations take an explicit element index and do not
 82  *   affect the position.  Absolute <i>get</i> and <i>put</i> operations throw
 83  *   an {@link IndexOutOfBoundsException} if the index argument exceeds the
 84  *   limit.  </p>
 85  *
 86  * </blockquote>
 87  *
 88  * <p> Data may also, of course, be transferred in to or out of a buffer by the
 89  * I/O operations of an appropriate channel, which are always relative to the
 90  * current position.
 91  *
 92  *
 93  * <h2> Marking and resetting </h2>
 94  *
 95  * <p> A buffer's <i>mark</i> is the index to which its position will be reset
 96  * when the {@link #reset reset} method is invoked.  The mark is not always
 97  * defined, but when it is defined it is never negative and is never greater
 98  * than the position.  If the mark is defined then it is discarded when the
 99  * position or the limit is adjusted to a value smaller than the mark.  If the
100  * mark is not defined then invoking the {@link #reset reset} method causes an
101  * {@link InvalidMarkException} to be thrown.
102  *
103  *
104  * <h2> Invariants </h2>
105  *
106  * <p> The following invariant holds for the mark, position, limit, and
107  * capacity values:
108  *
109  * <blockquote>
110  *     {@code 0} {@code <=}
111  *     <i>mark</i> {@code <=}
112  *     <i>position</i> {@code <=}
113  *     <i>limit</i> {@code <=}
114  *     <i>capacity</i>
115  * </blockquote>
116  *
117  * <p> A newly-created buffer always has a position of zero and a mark that is
118  * undefined.  The initial limit may be zero, or it may be some other value
119  * that depends upon the type of the buffer and the manner in which it is
120  * constructed.  Each element of a newly-allocated buffer is initialized
121  * to zero.
122  *
123  *
124  * <h2> Additional operations </h2>
125  *
126  * <p> In addition to methods for accessing the position, limit, and capacity
127  * values and for marking and resetting, this class also defines the following
128  * operations upon buffers:
129  *
130  * <ul>
131  *
132  *   <li><p> {@link #clear} makes a buffer ready for a new sequence of
133  *   channel-read or relative <i>put</i> operations: It sets the limit to the
134  *   capacity and the position to zero.  </p></li>
135  *
136  *   <li><p> {@link #flip} makes a buffer ready for a new sequence of
137  *   channel-write or relative <i>get</i> operations: It sets the limit to the
138  *   current position and then sets the position to zero.  </p></li>
139  *
140  *   <li><p> {@link #rewind} makes a buffer ready for re-reading the data that
141  *   it already contains: It leaves the limit unchanged and sets the position
142  *   to zero.  </p></li>
143  *
144  *   <li><p> The {@link #slice} and {@link #slice(int,int) slice(index,length)}
145  *   methods create a subsequence of a buffer: They leave the limit and the
146  *   position unchanged. </p></li>
147  *
148  *   <li><p> {@link #duplicate} creates a shallow copy of a buffer: It leaves
149  *   the limit and the position unchanged. </p></li>
150  *
151  * </ul>
152  *
153  *
154  * <h2> Read-only buffers </h2>
155  *
156  * <p> Every buffer is readable, but not every buffer is writable.  The
157  * mutation methods of each buffer class are specified as <i>optional
158  * operations</i> that will throw a {@link ReadOnlyBufferException} when
159  * invoked upon a read-only buffer.  A read-only buffer does not allow its
160  * content to be changed, but its mark, position, and limit values are mutable.
161  * Whether or not a buffer is read-only may be determined by invoking its
162  * {@link #isReadOnly isReadOnly} method.
163  *
164  *
165  * <h2> Thread safety </h2>
166  *
167  * <p> Buffers are not safe for use by multiple concurrent threads.  If a
168  * buffer is to be used by more than one thread then access to the buffer
169  * should be controlled by appropriate synchronization.
170  *
171  *
172  * <h2> Invocation chaining </h2>
173  *
174  * <p> Methods in this class that do not otherwise have a value to return are
175  * specified to return the buffer upon which they are invoked.  This allows
176  * method invocations to be chained; for example, the sequence of statements
177  *
178  * <blockquote><pre>
179  * b.flip();
180  * b.position(23);
181  * b.limit(42);</pre></blockquote>
182  *
183  * can be replaced by the single, more compact statement
184  *
185  * <blockquote><pre>
186  * b.flip().position(23).limit(42);</pre></blockquote>
187  *
188  *
189  * @author Mark Reinhold
190  * @author JSR-51 Expert Group
191  * @since 1.4
192  */
193 
194 public abstract class Buffer {
195     // Cached unsafe-access object
196     static final Unsafe UNSAFE = Unsafe.getUnsafe();
197 
198     static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
199 
200     /**
201      * The characteristics of Spliterators that traverse and split elements
202      * maintained in Buffers.
203      */
204     static final int SPLITERATOR_CHARACTERISTICS =
205         Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED;
206 
207     // Invariants: mark <= position <= limit <= capacity
208     private int mark = -1;
209     private int position = 0;
210     private int limit;
211     private int capacity;
212 
213     // Used by heap byte buffers or direct buffers with Unsafe access
214     // For heap byte buffers this field will be the address relative to the
215     // array base address and offset into that array. The address might
216     // not align on a word boundary for slices, nor align at a long word
217     // (8 byte) boundary for byte[] allocations on 32-bit systems.
218     // For direct buffers it is the start address of the memory region. The
219     // address might not align on a word boundary for slices, nor when created
220     // using JNI, see NewDirectByteBuffer(void*, long).
221     // Should ideally be declared final
222     // NOTE: hoisted here for speed in JNI GetDirectBufferAddress
223     long address;
224 
225     // Used by buffers generated by the memory access API (JEP-370)
226     final MemorySegmentProxy segment;
227 
228 
229     // Creates a new buffer with given address and capacity.
230     //
231     Buffer(long addr, int cap, MemorySegmentProxy segment) {
232         this.address = addr;
233         this.capacity = cap;
234         this.segment = segment;
235     }
236 
237     // Creates a new buffer with the given mark, position, limit, and capacity,
238     // after checking invariants.
239     //
240     Buffer(int mark, int pos, int lim, int cap, MemorySegmentProxy segment) {       // package-private
241         if (cap < 0)
242             throw createCapacityException(cap);
243         this.capacity = cap;
244         this.segment = segment;
245         limit(lim);
246         position(pos);
247         if (mark >= 0) {
248             if (mark > pos)
249                 throw new IllegalArgumentException("mark > position: ("
250                                                    + mark + " > " + pos + ")");
251             this.mark = mark;
252         }
253     }
254 
255     /**
256      * Returns an {@code IllegalArgumentException} indicating that the source
257      * and target are the same {@code Buffer}.  Intended for use in
258      * {@code put(src)} when the parameter is the {@code Buffer} on which the
259      * method is being invoked.
260      *
261      * @return  IllegalArgumentException
262      *          With a message indicating equal source and target buffers
263      */
264     static IllegalArgumentException createSameBufferException() {
265         return new IllegalArgumentException("The source buffer is this buffer");
266     }
267 
268     /**
269      * Verify that the capacity is nonnegative.
270      *
271      * @param  capacity
272      *         The new buffer's capacity, in $type$s
273      *
274      * @throws IllegalArgumentException
275      *         If the {@code capacity} is a negative integer
276      */
277     static IllegalArgumentException createCapacityException(int capacity) {
278         assert capacity < 0 : "capacity expected to be negative";
279         return new IllegalArgumentException("capacity < 0: ("
280             + capacity + " < 0)");
281     }
282 
283     /**
284      * Returns this buffer's capacity.
285      *
286      * @return  The capacity of this buffer
287      */
288     public final int capacity() {
289         return capacity;
290     }
291 
292     /**
293      * Returns this buffer's position.
294      *
295      * @return  The position of this buffer
296      */
297     public final int position() {
298         return position;
299     }
300 
301     /**
302      * Sets this buffer's position.  If the mark is defined and larger than the
303      * new position then it is discarded.
304      *
305      * @param  newPosition
306      *         The new position value; must be non-negative
307      *         and no larger than the current limit
308      *
309      * @return  This buffer
310      *
311      * @throws  IllegalArgumentException
312      *          If the preconditions on {@code newPosition} do not hold
313      */
314     public Buffer position(int newPosition) {
315         if (newPosition > limit | newPosition < 0)
316             throw createPositionException(newPosition);
317         if (mark > newPosition) mark = -1;
318         position = newPosition;
319         return this;
320     }
321 
322     /**
323      * Verify that {@code 0 < newPosition <= limit}
324      *
325      * @param newPosition
326      *        The new position value
327      *
328      * @throws IllegalArgumentException
329      *         If the specified position is out of bounds.
330      */
331     private IllegalArgumentException createPositionException(int newPosition) {
332         String msg = null;
333 
334         if (newPosition > limit) {
335             msg = "newPosition > limit: (" + newPosition + " > " + limit + ")";
336         } else { // assume negative
337             assert newPosition < 0 : "newPosition expected to be negative";
338             msg = "newPosition < 0: (" + newPosition + " < 0)";
339         }
340 
341         return new IllegalArgumentException(msg);
342     }
343 
344     /**
345      * Returns this buffer's limit.
346      *
347      * @return  The limit of this buffer
348      */
349     public final int limit() {
350         return limit;
351     }
352 
353     /**
354      * Sets this buffer's limit.  If the position is larger than the new limit
355      * then it is set to the new limit.  If the mark is defined and larger than
356      * the new limit then it is discarded.
357      *
358      * @param  newLimit
359      *         The new limit value; must be non-negative
360      *         and no larger than this buffer's capacity
361      *
362      * @return  This buffer
363      *
364      * @throws  IllegalArgumentException
365      *          If the preconditions on {@code newLimit} do not hold
366      */
367     public Buffer limit(int newLimit) {
368         if (newLimit > capacity | newLimit < 0)
369             throw createLimitException(newLimit);
370         limit = newLimit;
371         if (position > newLimit) position = newLimit;
372         if (mark > newLimit) mark = -1;
373         return this;
374     }
375 
376     /**
377      * Verify that {@code 0 < newLimit <= capacity}
378      *
379      * @param newLimit
380      *        The new limit value
381      *
382      * @throws IllegalArgumentException
383      *         If the specified limit is out of bounds.
384      */
385     private IllegalArgumentException createLimitException(int newLimit) {
386         String msg = null;
387 
388         if (newLimit > capacity) {
389             msg = "newLimit > capacity: (" + newLimit + " > " + capacity + ")";
390         } else { // assume negative
391             assert newLimit < 0 : "newLimit expected to be negative";
392             msg = "newLimit < 0: (" + newLimit + " < 0)";
393         }
394 
395         return new IllegalArgumentException(msg);
396     }
397 
398     /**
399      * Sets this buffer's mark at its position.
400      *
401      * @return  This buffer
402      */
403     public Buffer mark() {
404         mark = position;
405         return this;
406     }
407 
408     /**
409      * Resets this buffer's position to the previously-marked position.
410      *
411      * <p> Invoking this method neither changes nor discards the mark's
412      * value. </p>
413      *
414      * @return  This buffer
415      *
416      * @throws  InvalidMarkException
417      *          If the mark has not been set
418      */
419     public Buffer reset() {
420         int m = mark;
421         if (m < 0)
422             throw new InvalidMarkException();
423         position = m;
424         return this;
425     }
426 
427     /**
428      * Clears this buffer.  The position is set to zero, the limit is set to
429      * the capacity, and the mark is discarded.
430      *
431      * <p> Invoke this method before using a sequence of channel-read or
432      * <i>put</i> operations to fill this buffer.  For example:
433      *
434      * <blockquote><pre>
435      * buf.clear();     // Prepare buffer for reading
436      * in.read(buf);    // Read data</pre></blockquote>
437      *
438      * <p> This method does not actually erase the data in the buffer, but it
439      * is named as if it did because it will most often be used in situations
440      * in which that might as well be the case. </p>
441      *
442      * @return  This buffer
443      */
444     public Buffer clear() {
445         position = 0;
446         limit = capacity;
447         mark = -1;
448         return this;
449     }
450 
451     /**
452      * Flips this buffer.  The limit is set to the current position and then
453      * the position is set to zero.  If the mark is defined then it is
454      * discarded.
455      *
456      * <p> After a sequence of channel-read or <i>put</i> operations, invoke
457      * this method to prepare for a sequence of channel-write or relative
458      * <i>get</i> operations.  For example:
459      *
460      * <blockquote><pre>
461      * buf.put(magic);    // Prepend header
462      * in.read(buf);      // Read data into rest of buffer
463      * buf.flip();        // Flip buffer
464      * out.write(buf);    // Write header + data to channel</pre></blockquote>
465      *
466      * <p> This method is often used in conjunction with the {@link
467      * java.nio.ByteBuffer#compact compact} method when transferring data from
468      * one place to another.  </p>
469      *
470      * @return  This buffer
471      */
472     public Buffer flip() {
473         limit = position;
474         position = 0;
475         mark = -1;
476         return this;
477     }
478 
479     /**
480      * Rewinds this buffer.  The position is set to zero and the mark is
481      * discarded.
482      *
483      * <p> Invoke this method before a sequence of channel-write or <i>get</i>
484      * operations, assuming that the limit has already been set
485      * appropriately.  For example:
486      *
487      * <blockquote><pre>
488      * out.write(buf);    // Write remaining data
489      * buf.rewind();      // Rewind buffer
490      * buf.get(array);    // Copy data into array</pre></blockquote>
491      *
492      * @return  This buffer
493      */
494     public Buffer rewind() {
495         position = 0;
496         mark = -1;
497         return this;
498     }
499 
500     /**
501      * Returns the number of elements between the current position and the
502      * limit.
503      *
504      * @return  The number of elements remaining in this buffer
505      */
506     public final int remaining() {
507         int rem = limit - position;
508         return rem > 0 ? rem : 0;
509     }
510 
511     /**
512      * Tells whether there are any elements between the current position and
513      * the limit.
514      *
515      * @return  {@code true} if, and only if, there is at least one element
516      *          remaining in this buffer
517      */
518     public final boolean hasRemaining() {
519         return position < limit;
520     }
521 
522     /**
523      * Tells whether or not this buffer is read-only.
524      *
525      * @return  {@code true} if, and only if, this buffer is read-only
526      */
527     public abstract boolean isReadOnly();
528 
529     /**
530      * Tells whether or not this buffer is backed by an accessible
531      * array.
532      *
533      * <p> If this method returns {@code true} then the {@link #array() array}
534      * and {@link #arrayOffset() arrayOffset} methods may safely be invoked.
535      * </p>
536      *
537      * @return  {@code true} if, and only if, this buffer
538      *          is backed by an array and is not read-only
539      *
540      * @since 1.6
541      */
542     public abstract boolean hasArray();
543 
544     /**
545      * Returns the array that backs this
546      * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
547      *
548      * <p> This method is intended to allow array-backed buffers to be
549      * passed to native code more efficiently. Concrete subclasses
550      * provide more strongly-typed return values for this method.
551      *
552      * <p> Modifications to this buffer's content will cause the returned
553      * array's content to be modified, and vice versa.
554      *
555      * <p> Invoke the {@link #hasArray hasArray} method before invoking this
556      * method in order to ensure that this buffer has an accessible backing
557      * array.  </p>
558      *
559      * @return  The array that backs this buffer
560      *
561      * @throws  ReadOnlyBufferException
562      *          If this buffer is backed by an array but is read-only
563      *
564      * @throws  UnsupportedOperationException
565      *          If this buffer is not backed by an accessible array
566      *
567      * @since 1.6
568      */
569     public abstract Object array();
570 
571     /**
572      * Returns the offset within this buffer's backing array of the first
573      * element of the buffer&nbsp;&nbsp;<i>(optional operation)</i>.
574      *
575      * <p> If this buffer is backed by an array then buffer position <i>p</i>
576      * corresponds to array index <i>p</i>&nbsp;+&nbsp;{@code arrayOffset()}.
577      *
578      * <p> Invoke the {@link #hasArray hasArray} method before invoking this
579      * method in order to ensure that this buffer has an accessible backing
580      * array.  </p>
581      *
582      * @return  The offset within this buffer's array
583      *          of the first element of the buffer
584      *
585      * @throws  ReadOnlyBufferException
586      *          If this buffer is backed by an array but is read-only
587      *
588      * @throws  UnsupportedOperationException
589      *          If this buffer is not backed by an accessible array
590      *
591      * @since 1.6
592      */
593     public abstract int arrayOffset();
594 
595     /**
596      * Tells whether or not this buffer is
597      * <a href="ByteBuffer.html#direct"><i>direct</i></a>.
598      *
599      * @return  {@code true} if, and only if, this buffer is direct
600      *
601      * @since 1.6
602      */
603     public abstract boolean isDirect();
604 
605     /**
606      * Creates a new buffer whose content is a shared subsequence of
607      * this buffer's content.
608      *
609      * <p> The content of the new buffer will start at this buffer's current
610      * position.  Changes to this buffer's content will be visible in the new
611      * buffer, and vice versa; the two buffers' position, limit, and mark
612      * values will be independent.
613      *
614      * <p> The new buffer's position will be zero, its capacity and its limit
615      * will be the number of elements remaining in this buffer, its mark will be
616      * undefined. The new buffer will be direct if, and only if, this buffer is
617      * direct, and it will be read-only if, and only if, this buffer is
618      * read-only.  </p>
619      *
620      * @return  The new buffer
621      *
622      * @since 9
623      */
624     public abstract Buffer slice();
625 
626     /**
627      * Creates a new buffer whose content is a shared subsequence of
628      * this buffer's content.
629      *
630      * <p> The content of the new buffer will start at position {@code index}
631      * in this buffer, and will contain {@code length} elements. Changes to
632      * this buffer's content will be visible in the new buffer, and vice versa;
633      * the two buffers' position, limit, and mark values will be independent.
634      *
635      * <p> The new buffer's position will be zero, its capacity and its limit
636      * will be {@code length}, its mark will be undefined. The new buffer will
637      * be direct if, and only if, this buffer is direct, and it will be
638      * read-only if, and only if, this buffer is read-only.  </p>
639      *
640      * @param   index
641      *          The position in this buffer at which the content of the new
642      *          buffer will start; must be non-negative and no larger than
643      *          {@link #limit() limit()}
644      *
645      * @param   length
646      *          The number of elements the new buffer will contain; must be
647      *          non-negative and no larger than {@code limit() - index}
648      *
649      * @return  The new buffer
650      *
651      * @throws  IndexOutOfBoundsException
652      *          If {@code index} is negative or greater than {@code limit()},
653      *          {@code length} is negative, or {@code length > limit() - index}
654      *
655      * @since 13
656      */
657     public abstract Buffer slice(int index, int length);
658 
659     /**
660      * Creates a new buffer that shares this buffer's content.
661      *
662      * <p> The content of the new buffer will be that of this buffer.  Changes
663      * to this buffer's content will be visible in the new buffer, and vice
664      * versa; the two buffers' position, limit, and mark values will be
665      * independent.
666      *
667      * <p> The new buffer's capacity, limit, position and mark values will be
668      * identical to those of this buffer. The new buffer will be direct if, and
669      * only if, this buffer is direct, and it will be read-only if, and only if,
670      * this buffer is read-only.  </p>
671      *
672      * @return  The new buffer
673      *
674      * @since 9
675      */
676     public abstract Buffer duplicate();
677 
678 
679     // -- Package-private methods for bounds checking, etc. --
680 
681     /**
682      *
683      * @return the base reference, paired with the address
684      * field, which in combination can be used for unsafe access into a heap
685      * buffer or direct byte buffer (and views of).
686      */
687     abstract Object base();
688 
689     /**
690      * Checks the current position against the limit, throwing a {@link
691      * BufferUnderflowException} if it is not smaller than the limit, and then
692      * increments the position.
693      *
694      * @return  The current position value, before it is incremented
695      */
696     final int nextGetIndex() {                          // package-private
697         int p = position;
698         if (p >= limit)
699             throw new BufferUnderflowException();
700         position = p + 1;
701         return p;
702     }
703 
704     final int nextGetIndex(int nb) {                    // package-private
705         int p = position;
706         if (limit - p < nb)
707             throw new BufferUnderflowException();
708         position = p + nb;
709         return p;
710     }
711 
712     /**
713      * Checks the current position against the limit, throwing a {@link
714      * BufferOverflowException} if it is not smaller than the limit, and then
715      * increments the position.
716      *
717      * @return  The current position value, before it is incremented
718      */
719     final int nextPutIndex() {                          // package-private
720         int p = position;
721         if (p >= limit)
722             throw new BufferOverflowException();
723         position = p + 1;
724         return p;
725     }
726 
727     final int nextPutIndex(int nb) {                    // package-private
728         int p = position;
729         if (limit - p < nb)
730             throw new BufferOverflowException();
731         position = p + nb;
732         return p;
733     }
734 
735     /**
736      * Checks the given index against the limit, throwing an {@link
737      * IndexOutOfBoundsException} if it is not smaller than the limit
738      * or is smaller than zero.
739      */
740     final int checkIndex(int i) {                       // package-private
741         return Objects.checkIndex(i, limit);
742     }
743 
744     final int checkIndex(int i, int nb) {               // package-private
745         if ((i < 0) || (nb > limit - i))
746             throw new IndexOutOfBoundsException();
747         return i;
748     }
749 
750     final int markValue() {                             // package-private
751         return mark;
752     }
753 
754     final void discardMark() {                          // package-private
755         mark = -1;
756     }
757 
758     @ForceInline
759     final ScopedMemoryAccess.Scope scope() {
760         if (segment != null) {
761             return segment.scope();
762         } else {
763             return null;
764         }
765     }
766 
767     final void checkScope() {
768         ScopedMemoryAccess.Scope scope = scope();
769         if (scope != null) {
770             scope.checkValidState();
771         }
772     }
773 
774     static {
775         // setup access to this package in SharedSecrets
776         SharedSecrets.setJavaNioAccess(
777             new JavaNioAccess() {
778                 @Override
779                 public BufferPool getDirectBufferPool() {
780                     return Bits.BUFFER_POOL;
781                 }
782 
783                 @Override
784                 public ByteBuffer newDirectByteBuffer(long addr, int cap, Object obj, MemorySegmentProxy segment) {
785                     return new DirectByteBuffer(addr, cap, obj, segment);
786                 }
787 
788                 @Override
789                 public ByteBuffer newMappedByteBuffer(UnmapperProxy unmapperProxy, long address, int cap, Object obj, MemorySegmentProxy segment) {
790                     return new DirectByteBuffer(address, cap, obj, unmapperProxy.fileDescriptor(), unmapperProxy.isSync(), segment);
791                 }
792 
793                 @Override
794                 public ByteBuffer newHeapByteBuffer(byte[] hb, int offset, int capacity, MemorySegmentProxy segment) {
795                     return new HeapByteBuffer(hb, -1, 0, capacity, capacity, offset, segment);
796                 }
797 
798                 @Override
799                 public Object getBufferBase(ByteBuffer bb) {
800                     return bb.base();
801                 }
802 
803                 @Override
804                 public long getBufferAddress(ByteBuffer bb) {
805                     return bb.address;
806                 }
807 
808                 @Override
809                 public UnmapperProxy unmapper(ByteBuffer bb) {
810                     if (bb instanceof MappedByteBuffer) {
811                         return ((MappedByteBuffer)bb).unmapper();
812                     } else {
813                         return null;
814                     }
815                 }
816 
817                 @Override
818                 public MemorySegmentProxy bufferSegment(Buffer buffer) {
819                     return buffer.segment;
820                 }
821 
822                 @Override
823                 public Runnable acquireScope(Buffer buffer, boolean async) {
824                     var scope = buffer.scope();
825                     if (scope == null) {
826                         return null;
827                     }
828                     if (async && scope.ownerThread() != null) {
829                         throw new IllegalStateException("Confined scope not supported");
830                     }
831                     scope.acquire0();
832                     return scope::release0;
833                 }
834 
835                 @Override
836                 public void force(FileDescriptor fd, long address, boolean isSync, long offset, long size) {
837                     MappedMemoryUtils.force(fd, address, isSync, offset, size);
838                 }
839 
840                 @Override
841                 public void load(long address, boolean isSync, long size) {
842                     MappedMemoryUtils.load(address, isSync, size);
843                 }
844 
845                 @Override
846                 public void unload(long address, boolean isSync, long size) {
847                     MappedMemoryUtils.unload(address, isSync, size);
848                 }
849 
850                 @Override
851                 public boolean isLoaded(long address, boolean isSync, long size) {
852                     return MappedMemoryUtils.isLoaded(address, isSync, size);
853                 }
854 
855                 @Override
856                 public void reserveMemory(long size, long cap) {
857                     Bits.reserveMemory(size, cap);
858                 }
859 
860                 @Override
861                 public void unreserveMemory(long size, long cap) {
862                     Bits.unreserveMemory(size, cap);
863                 }
864 
865                 @Override
866                 public int pageSize() {
867                     return Bits.pageSize();
868                 }
869             });
870     }
871 
872 }