1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.  Oracle designates this
9  * particular file as subject to the "Classpath" exception as provided
10  * by Oracle in the LICENSE file that accompanied this code.
11  *
12  * This code is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  * version 2 for more details (a copy is included in the LICENSE file that
16  * accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License version
19  * 2 along with this work; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23  * or visit www.oracle.com if you need additional information or have any
24  * questions.
25  */
26 
27 package java.nio;
28 
29 import java.io.FileDescriptor;
30 import java.util.Objects;
31 
32 import dalvik.annotation.codegen.CovariantReturnType;
33 import dalvik.annotation.compat.VersionCodes;
34 import dalvik.system.VMRuntime;
35 import libcore.io.Memory;
36 import sun.misc.Cleaner;
37 import sun.nio.ch.DirectBuffer;
38 
39 // Not final because it is extended in tests.
40 /** @hide */
41 public class DirectByteBuffer extends MappedByteBuffer implements DirectBuffer {
42 
43     /**
44      * Stores the details of the memory backing a DirectByteBuffer. This could be a pointer
45      * (passed through from JNI or resulting from a mapping) or a non-movable byte array allocated
46      * from Java. Each MemoryRef also has an isAccessible associated with it, which determines
47      * whether the underlying memory is "accessible". The notion of "accessibility" is usually
48      * defined by the allocator of the reference, and is separate from the accessibility of the
49      * memory as defined by the underlying system.
50      *
51      * A single MemoryRef instance is shared across all slices and duplicates of a given buffer.
52      */
53     final static class MemoryRef {
54         byte[] buffer;
55         long allocatedAddress;
56         final int offset;
57         boolean isAccessible;
58         boolean isFreed;
59 
60 
61         // Reference to original DirectByteBuffer that held this MemoryRef. The field is set
62         // only for the MemoryRef created through JNI NewDirectByteBuffer(void*, long) function.
63         // This allows users of JNI NewDirectByteBuffer to create a PhantomReference on the
64         // DirectByteBuffer instance that will only be put in the associated ReferenceQueue when
65         // the underlying memory is not referenced by any DirectByteBuffer instance. The
66         // MemoryRef can outlive the original DirectByteBuffer instance if, for example, slice()
67         // or asReadOnlyBuffer() are called and all strong references to the original DirectByteBuffer
68         // are discarded.
69         final Object originalBufferObject;
70 
MemoryRef(int capacity)71         MemoryRef(int capacity) {
72             VMRuntime runtime = VMRuntime.getRuntime();
73             buffer = (byte[]) runtime.newNonMovableArray(byte.class, capacity + 7);
74             allocatedAddress = runtime.addressOf(buffer);
75             // Offset is set to handle the alignment: http://b/16449607
76             offset = (int) (((allocatedAddress + 7) & ~(long) 7) - allocatedAddress);
77             isAccessible = true;
78             isFreed = false;
79             originalBufferObject = null;
80         }
81 
MemoryRef(long allocatedAddress, Object originalBufferObject)82         MemoryRef(long allocatedAddress, Object originalBufferObject) {
83             buffer = null;
84             this.allocatedAddress = allocatedAddress;
85             this.offset = 0;
86             this.originalBufferObject = originalBufferObject;
87             isAccessible = true;
88         }
89 
free()90         void free() {
91             buffer = null;
92             allocatedAddress = 0;
93             isAccessible = false;
94             isFreed = true;
95         }
96     }
97 
98     final Cleaner cleaner;
99     final MemoryRef memoryRef;
100 
DirectByteBuffer(int capacity, MemoryRef memoryRef)101     DirectByteBuffer(int capacity, MemoryRef memoryRef) {
102         super(-1, 0, capacity, capacity, memoryRef.buffer, memoryRef.offset);
103         // Only have references to java objects, no need for a cleaner since the GC will do all
104         // the work.
105         this.memoryRef = memoryRef;
106         this.address = memoryRef.allocatedAddress + memoryRef.offset;
107         cleaner = null;
108         this.isReadOnly = false;
109     }
110 
111     // Invoked only by JNI: NewDirectByteBuffer(void*, long)
112     @SuppressWarnings("unused")
DirectByteBuffer(long addr, int cap)113     private DirectByteBuffer(long addr, int cap) {
114         super(-1, 0, cap, cap);
115         memoryRef = new MemoryRef(addr, this);
116         address = addr;
117         cleaner = null;
118     }
119 
120     // BEGIN Android-changed: Remove MemorySegmentProxy and merge with read-only buffer.
121     /** @hide */
DirectByteBuffer(int cap, long addr, FileDescriptor fd, Runnable unmapper, boolean isReadOnly)122     public DirectByteBuffer(int cap, long addr,
123                             FileDescriptor fd,
124                             Runnable unmapper,
125                             boolean isReadOnly) {
126         super(-1, 0, cap, cap, fd, false);
127         this.isReadOnly = isReadOnly;
128         memoryRef = new MemoryRef(addr, null);
129         address = addr;
130         cleaner = Cleaner.create(memoryRef, unmapper);
131     }
132     // END Android-changed: Remove MemorySegmentProxy and merge with read-only buffer.
133 
134     // BEGIN Android-changed: Android needs MemoryRef for direct allocated buffer.
135     // For duplicates and slices
DirectByteBuffer(MemoryRef memoryRef, int mark, int pos, int lim, int cap, int off)136     DirectByteBuffer(MemoryRef memoryRef,         // package-private
137                      int mark, int pos, int lim, int cap,
138                      int off) {
139         this(memoryRef, mark, pos, lim, cap, off, false);
140     }
141 
DirectByteBuffer(MemoryRef memoryRef, int mark, int pos, int lim, int cap, int off, boolean isReadOnly)142     DirectByteBuffer(MemoryRef memoryRef,         // package-private
143                      int mark, int pos, int lim, int cap,
144                      int off, boolean isReadOnly) {
145         super(mark, pos, lim, cap, memoryRef.buffer, off);
146         this.isReadOnly = isReadOnly;
147         this.memoryRef = memoryRef;
148         address = memoryRef.allocatedAddress + off;
149         cleaner = null;
150     }
151     // END Android-changed: Android needs MemoryRef for direct allocated buffer.
152 
153     @Override
attachment()154     public final Object attachment() {
155         return memoryRef;
156     }
157 
158     @Override
cleaner()159     public final Cleaner cleaner() {
160         return cleaner;
161     }
162 
163     @Override
base()164     Object base() {
165         return null;
166     }
167 
168     @Override
slice()169     public final MappedByteBuffer slice() {
170         if (!memoryRef.isAccessible) {
171         throw new IllegalStateException("buffer is inaccessible");
172         }
173         int pos = position();
174         int lim = limit();
175         assert (pos <= lim);
176         int rem = (pos <= lim ? lim - pos : 0);
177         int off = pos + offset;
178         assert (off >= 0);
179         return new DirectByteBuffer(memoryRef, -1, 0, rem, rem, off, isReadOnly);
180     }
181 
182     @Override
slice(int index, int length)183     public final MappedByteBuffer slice(int index, int length) {
184         if (!memoryRef.isAccessible) {
185             throw new IllegalStateException("buffer is inaccessible");
186         }
187         Objects.checkFromIndexSize(index, length, limit());
188         return new DirectByteBuffer(memoryRef,
189                                               -1,
190                                               0,
191                                               length,
192                                               length,
193         // Android-changed: The constructor's argument means the offset from the allocated address.
194                                               // index << 0,
195                                               index + offset,
196                                               isReadOnly);
197     }
198 
199     @Override
duplicate()200     public final MappedByteBuffer duplicate() {
201         if (memoryRef.isFreed) {
202             throw new IllegalStateException("buffer has been freed");
203         }
204         return new DirectByteBuffer(memoryRef,
205                 this.markValue(),
206                 this.position(),
207                 this.limit(),
208                 this.capacity(),
209                 offset,
210                 isReadOnly);
211     }
212 
213     @Override
asReadOnlyBuffer()214     public final ByteBuffer asReadOnlyBuffer() {
215         if (memoryRef.isFreed) {
216             throw new IllegalStateException("buffer has been freed");
217         }
218         return new DirectByteBuffer(memoryRef,
219                 this.markValue(),
220                 this.position(),
221                 this.limit(),
222                 this.capacity(),
223                 offset,
224                 true);
225     }
226 
227     @Override
address()228     public final long address() {
229         return address;
230     }
231 
ix(int i)232     private long ix(int i) {
233         return address + i;
234     }
235 
get(long a)236     private byte get(long a) {
237         return Memory.peekByte(a);
238     }
239 
240     @Override
get()241     public final byte get() {
242         if (!memoryRef.isAccessible) {
243             throw new IllegalStateException("buffer is inaccessible");
244         }
245         return get(ix(nextGetIndex()));
246     }
247 
248     @Override
get(int i)249     public final byte get(int i) {
250         if (!memoryRef.isAccessible) {
251             throw new IllegalStateException("buffer is inaccessible");
252         }
253         return get(ix(checkIndex(i)));
254     }
255 
256     // This method is not declared final because it is overridden in tests.
257     @Override
get(byte[] dst, int dstOffset, int length)258     public ByteBuffer get(byte[] dst, int dstOffset, int length) {
259         if (!memoryRef.isAccessible) {
260             throw new IllegalStateException("buffer is inaccessible");
261         }
262         checkBounds(dstOffset, length, dst.length);
263         int pos = position();
264         int lim = limit();
265         assert (pos <= lim);
266         int rem = (pos <= lim ? lim - pos : 0);
267         if (length > rem)
268             throw new BufferUnderflowException();
269         Memory.peekByteArray(ix(pos),
270                 dst, dstOffset, length);
271         position = pos + length;
272         return this;
273     }
274 
put(long a, byte x)275     private ByteBuffer put(long a, byte x) {
276         Memory.pokeByte(a, x);
277         return this;
278     }
279 
280     @Override
put(ByteBuffer src)281     public ByteBuffer put(ByteBuffer src) {
282         if (!memoryRef.isAccessible) {
283             throw new IllegalStateException("buffer is inaccessible");
284         }
285         return super.put(src);
286     }
287 
288     @Override
put(byte x)289     public final ByteBuffer put(byte x) {
290         if (!memoryRef.isAccessible) {
291             throw new IllegalStateException("buffer is inaccessible");
292         }
293         if (isReadOnly) {
294             throw new ReadOnlyBufferException();
295         }
296         put(ix(nextPutIndex()), x);
297         return this;
298     }
299 
300     @Override
put(int i, byte x)301     public final ByteBuffer put(int i, byte x) {
302         if (!memoryRef.isAccessible) {
303             throw new IllegalStateException("buffer is inaccessible");
304         }
305         if (isReadOnly) {
306             throw new ReadOnlyBufferException();
307         }
308         put(ix(checkIndex(i)), x);
309         return this;
310     }
311 
312     // This method is not declared final because it is overridden in tests.
313     @Override
put(byte[] src, int srcOffset, int length)314     public ByteBuffer put(byte[] src, int srcOffset, int length) {
315         if (!memoryRef.isAccessible) {
316             throw new IllegalStateException("buffer is inaccessible");
317         }
318         if (isReadOnly) {
319             throw new ReadOnlyBufferException();
320         }
321         checkBounds(srcOffset, length, src.length);
322         int pos = position();
323         int lim = limit();
324         assert (pos <= lim);
325         int rem = (pos <= lim ? lim - pos : 0);
326         if (length > rem)
327             throw new BufferOverflowException();
328         Memory.pokeByteArray(ix(pos),
329                 src, srcOffset, length);
330         position = pos + length;
331         return this;
332     }
333 
334     // Android-changed: covariant overloads of *Buffer methods that return this.
335     @CovariantReturnType(returnType = MappedByteBuffer.class, presentAfter = 34)
336     @Override
compact()337     public final ByteBuffer compact() {
338         if (!memoryRef.isAccessible) {
339             throw new IllegalStateException("buffer is inaccessible");
340         }
341         if (isReadOnly) {
342             throw new ReadOnlyBufferException();
343         }
344         int pos = position();
345         int lim = limit();
346         assert (pos <= lim);
347         int rem = (pos <= lim ? lim - pos : 0);
348         System.arraycopy(hb, position + offset, hb, offset, remaining());
349         position(rem);
350         limit(capacity());
351         discardMark();
352         return this;
353     }
354 
355     @Override
isDirect()356     public final boolean isDirect() {
357         return true;
358     }
359 
360     @Override
isReadOnly()361     public final boolean isReadOnly() {
362         return isReadOnly;
363     }
364 
365     // Used by java.nio.Bits
366     @Override
_get(int i)367     final byte _get(int i) {                          // package-private
368         return get(i);
369     }
370 
371     // Used by java.nio.Bits
372     @Override
_put(int i, byte b)373     final void _put(int i, byte b) {                  // package-private
374         put(i, b);
375     }
376 
377     @Override
getChar()378     public final char getChar() {
379         if (!memoryRef.isAccessible) {
380             throw new IllegalStateException("buffer is inaccessible");
381         }
382         int newPosition = position + Character.BYTES;
383         if (newPosition > limit()) {
384             throw new BufferUnderflowException();
385         }
386         char x = (char) Memory.peekShort(ix(position), !nativeByteOrder);
387         position = newPosition;
388         return x;
389     }
390 
391     @Override
getChar(int i)392     public final char getChar(int i) {
393         if (!memoryRef.isAccessible) {
394             throw new IllegalStateException("buffer is inaccessible");
395         }
396         checkIndex(i, Character.BYTES);
397         return (char) Memory.peekShort(ix(i), !nativeByteOrder);
398     }
399 
400     @Override
getCharUnchecked(int i)401     char getCharUnchecked(int i) {
402         if (!memoryRef.isAccessible) {
403             throw new IllegalStateException("buffer is inaccessible");
404         }
405         return (char) Memory.peekShort(ix(i), !nativeByteOrder);
406     }
407 
408     @Override
getUnchecked(int pos, char[] dst, int dstOffset, int length)409     void getUnchecked(int pos, char[] dst, int dstOffset, int length) {
410         if (!memoryRef.isAccessible) {
411             throw new IllegalStateException("buffer is inaccessible");
412         }
413         Memory.peekCharArray(ix(pos),
414                 dst, dstOffset, length, !nativeByteOrder);
415     }
416 
putChar(long a, char x)417     private ByteBuffer putChar(long a, char x) {
418         Memory.pokeShort(a, (short) x, !nativeByteOrder);
419         return this;
420     }
421 
422     @Override
putChar(char x)423     public final ByteBuffer putChar(char x) {
424         if (!memoryRef.isAccessible) {
425             throw new IllegalStateException("buffer is inaccessible");
426         }
427         if (isReadOnly) {
428             throw new ReadOnlyBufferException();
429         }
430         putChar(ix(nextPutIndex(Character.BYTES)), x);
431         return this;
432     }
433 
434     @Override
putChar(int i, char x)435     public final ByteBuffer putChar(int i, char x) {
436         if (!memoryRef.isAccessible) {
437             throw new IllegalStateException("buffer is inaccessible");
438         }
439         if (isReadOnly) {
440             throw new ReadOnlyBufferException();
441         }
442         putChar(ix(checkIndex(i, Character.BYTES)), x);
443         return this;
444     }
445 
446     @Override
putCharUnchecked(int i, char x)447     void putCharUnchecked(int i, char x) {
448         if (!memoryRef.isAccessible) {
449             throw new IllegalStateException("buffer is inaccessible");
450         }
451         putChar(ix(i), x);
452     }
453 
454     @Override
putUnchecked(int pos, char[] src, int srcOffset, int length)455     void putUnchecked(int pos, char[] src, int srcOffset, int length) {
456         if (!memoryRef.isAccessible) {
457             throw new IllegalStateException("buffer is inaccessible");
458         }
459         Memory.pokeCharArray(ix(pos),
460                 src, srcOffset, length, !nativeByteOrder);
461     }
462 
463     @Override
asCharBuffer()464     public final CharBuffer asCharBuffer() {
465         if (memoryRef.isFreed) {
466             throw new IllegalStateException("buffer has been freed");
467         }
468         int off = this.position();
469         int lim = this.limit();
470         assert (off <= lim);
471         int rem = (off <= lim ? lim - off : 0);
472         int size = rem >> 1;
473         return new ByteBufferAsCharBuffer(this,
474                 -1,
475                 0,
476                 size,
477                 size,
478                 off,
479                 order());
480     }
481 
getShort(long a)482     private short getShort(long a) {
483         return Memory.peekShort(a, !nativeByteOrder);
484     }
485 
486     @Override
getShort()487     public final short getShort() {
488         if (!memoryRef.isAccessible) {
489             throw new IllegalStateException("buffer is inaccessible");
490         }
491         return getShort(ix(nextGetIndex(Short.BYTES)));
492     }
493 
494     @Override
getShort(int i)495     public final short getShort(int i) {
496         if (!memoryRef.isAccessible) {
497             throw new IllegalStateException("buffer is inaccessible");
498         }
499         return getShort(ix(checkIndex(i, Short.BYTES)));
500     }
501 
502     @Override
getShortUnchecked(int i)503     short getShortUnchecked(int i) {
504         if (!memoryRef.isAccessible) {
505             throw new IllegalStateException("buffer is inaccessible");
506         }
507         return getShort(ix(i));
508     }
509 
510     @Override
getUnchecked(int pos, short[] dst, int dstOffset, int length)511     void getUnchecked(int pos, short[] dst, int dstOffset, int length) {
512         if (!memoryRef.isAccessible) {
513             throw new IllegalStateException("buffer is inaccessible");
514         }
515         Memory.peekShortArray(ix(pos),
516                 dst, dstOffset, length, !nativeByteOrder);
517     }
518 
putShort(long a, short x)519     private ByteBuffer putShort(long a, short x) {
520         Memory.pokeShort(a, x, !nativeByteOrder);
521         return this;
522     }
523 
524     @Override
putShort(short x)525     public final ByteBuffer putShort(short x) {
526         if (!memoryRef.isAccessible) {
527             throw new IllegalStateException("buffer is inaccessible");
528         }
529         if (isReadOnly) {
530             throw new ReadOnlyBufferException();
531         }
532         putShort(ix(nextPutIndex(Short.BYTES)), x);
533         return this;
534     }
535 
536     @Override
putShort(int i, short x)537     public final ByteBuffer putShort(int i, short x) {
538         if (!memoryRef.isAccessible) {
539             throw new IllegalStateException("buffer is inaccessible");
540         }
541         if (isReadOnly) {
542             throw new ReadOnlyBufferException();
543         }
544         putShort(ix(checkIndex(i, Short.BYTES)), x);
545         return this;
546     }
547 
548     @Override
putShortUnchecked(int i, short x)549     void putShortUnchecked(int i, short x) {
550         if (!memoryRef.isAccessible) {
551             throw new IllegalStateException("buffer is inaccessible");
552         }
553         putShort(ix(i), x);
554     }
555 
556     @Override
putUnchecked(int pos, short[] src, int srcOffset, int length)557     void putUnchecked(int pos, short[] src, int srcOffset, int length) {
558         if (!memoryRef.isAccessible) {
559             throw new IllegalStateException("buffer is inaccessible");
560         }
561         Memory.pokeShortArray(ix(pos),
562                 src, srcOffset, length, !nativeByteOrder);
563     }
564 
565     @Override
asShortBuffer()566     public final ShortBuffer asShortBuffer() {
567         if (memoryRef.isFreed) {
568             throw new IllegalStateException("buffer has been freed");
569         }
570         int off = this.position();
571         int lim = this.limit();
572         assert (off <= lim);
573         int rem = (off <= lim ? lim - off : 0);
574         int size = rem >> 1;
575         return new ByteBufferAsShortBuffer(this,
576                 -1,
577                 0,
578                 size,
579                 size,
580                 off,
581                 order());
582     }
583 
getInt(long a)584     private int getInt(long a) {
585         return Memory.peekInt(a, !nativeByteOrder);
586     }
587 
588     @Override
getInt()589     public int getInt() {
590         if (!memoryRef.isAccessible) {
591             throw new IllegalStateException("buffer is inaccessible");
592         }
593         return getInt(ix(nextGetIndex(Integer.BYTES)));
594     }
595 
596     @Override
getInt(int i)597     public int getInt(int i) {
598         if (!memoryRef.isAccessible) {
599             throw new IllegalStateException("buffer is inaccessible");
600         }
601         return getInt(ix(checkIndex(i, (Integer.BYTES))));
602     }
603 
604     @Override
getIntUnchecked(int i)605     final int getIntUnchecked(int i) {
606         if (!memoryRef.isAccessible) {
607             throw new IllegalStateException("buffer is inaccessible");
608         }
609         return getInt(ix(i));
610     }
611 
612     @Override
getUnchecked(int pos, int[] dst, int dstOffset, int length)613     final void getUnchecked(int pos, int[] dst, int dstOffset, int length) {
614         if (!memoryRef.isAccessible) {
615             throw new IllegalStateException("buffer is inaccessible");
616         }
617         Memory.peekIntArray(ix(pos),
618                 dst, dstOffset, length, !nativeByteOrder);
619     }
620 
putInt(long a, int x)621     private ByteBuffer putInt(long a, int x) {
622         Memory.pokeInt(a, x, !nativeByteOrder);
623         return this;
624     }
625 
626     @Override
putInt(int x)627     public final ByteBuffer putInt(int x) {
628         if (!memoryRef.isAccessible) {
629             throw new IllegalStateException("buffer is inaccessible");
630         }
631         if (isReadOnly) {
632             throw new ReadOnlyBufferException();
633         }
634         putInt(ix(nextPutIndex(Integer.BYTES)), x);
635         return this;
636     }
637 
638     @Override
putInt(int i, int x)639     public final ByteBuffer putInt(int i, int x) {
640         if (!memoryRef.isAccessible) {
641             throw new IllegalStateException("buffer is inaccessible");
642         }
643         if (isReadOnly) {
644             throw new ReadOnlyBufferException();
645         }
646         putInt(ix(checkIndex(i, Integer.BYTES)), x);
647         return this;
648     }
649 
650     @Override
putIntUnchecked(int i, int x)651     final void putIntUnchecked(int i, int x) {
652         if (!memoryRef.isAccessible) {
653             throw new IllegalStateException("buffer is inaccessible");
654         }
655         putInt(ix(i), x);
656     }
657 
658     @Override
putUnchecked(int pos, int[] src, int srcOffset, int length)659     final void putUnchecked(int pos, int[] src, int srcOffset, int length) {
660         if (!memoryRef.isAccessible) {
661             throw new IllegalStateException("buffer is inaccessible");
662         }
663         Memory.pokeIntArray(ix(pos),
664                 src, srcOffset, length, !nativeByteOrder);
665     }
666 
667     @Override
asIntBuffer()668     public final IntBuffer asIntBuffer() {
669         if (memoryRef.isFreed) {
670             throw new IllegalStateException("buffer has been freed");
671         }
672         int off = this.position();
673         int lim = this.limit();
674         assert (off <= lim);
675         int rem = (off <= lim ? lim - off : 0);
676         int size = rem >> 2;
677         return new ByteBufferAsIntBuffer(this,
678                 -1,
679                 0,
680                 size,
681                 size,
682                 off,
683                 order());
684     }
685 
getLong(long a)686     private long getLong(long a) {
687         return Memory.peekLong(a, !nativeByteOrder);
688     }
689 
690     @Override
getLong()691     public final long getLong() {
692         if (!memoryRef.isAccessible) {
693             throw new IllegalStateException("buffer is inaccessible");
694         }
695         return getLong(ix(nextGetIndex(Long.BYTES)));
696     }
697 
698     @Override
getLong(int i)699     public final long getLong(int i) {
700         if (!memoryRef.isAccessible) {
701             throw new IllegalStateException("buffer is inaccessible");
702         }
703         return getLong(ix(checkIndex(i, Long.BYTES)));
704     }
705 
706     @Override
getLongUnchecked(int i)707     final long getLongUnchecked(int i) {
708         if (!memoryRef.isAccessible) {
709             throw new IllegalStateException("buffer is inaccessible");
710         }
711         return getLong(ix(i));
712     }
713 
714     @Override
getUnchecked(int pos, long[] dst, int dstOffset, int length)715     final void getUnchecked(int pos, long[] dst, int dstOffset, int length) {
716         if (!memoryRef.isAccessible) {
717             throw new IllegalStateException("buffer is inaccessible");
718         }
719         Memory.peekLongArray(ix(pos),
720                 dst, dstOffset, length, !nativeByteOrder);
721     }
722 
putLong(long a, long x)723     private ByteBuffer putLong(long a, long x) {
724         Memory.pokeLong(a, x, !nativeByteOrder);
725         return this;
726     }
727 
728     @Override
putLong(long x)729     public final ByteBuffer putLong(long x) {
730         if (!memoryRef.isAccessible) {
731             throw new IllegalStateException("buffer is inaccessible");
732         }
733         if (isReadOnly) {
734             throw new ReadOnlyBufferException();
735         }
736         putLong(ix(nextPutIndex(Long.BYTES)), x);
737         return this;
738     }
739 
740     @Override
putLong(int i, long x)741     public final ByteBuffer putLong(int i, long x) {
742         if (!memoryRef.isAccessible) {
743             throw new IllegalStateException("buffer is inaccessible");
744         }
745         if (isReadOnly) {
746             throw new ReadOnlyBufferException();
747         }
748         putLong(ix(checkIndex(i, Long.BYTES)), x);
749         return this;
750     }
751 
752     @Override
putLongUnchecked(int i, long x)753     final void putLongUnchecked(int i, long x) {
754         if (!memoryRef.isAccessible) {
755             throw new IllegalStateException("buffer is inaccessible");
756         }
757         putLong(ix(i), x);
758     }
759 
760     @Override
putUnchecked(int pos, long[] src, int srcOffset, int length)761     final void putUnchecked(int pos, long[] src, int srcOffset, int length) {
762         if (!memoryRef.isAccessible) {
763             throw new IllegalStateException("buffer is inaccessible");
764         }
765         Memory.pokeLongArray(ix(pos),
766                 src, srcOffset, length, !nativeByteOrder);
767     }
768 
769     @Override
asLongBuffer()770     public final LongBuffer asLongBuffer() {
771         if (memoryRef.isFreed) {
772             throw new IllegalStateException("buffer has been freed");
773         }
774         int off = this.position();
775         int lim = this.limit();
776         assert (off <= lim);
777         int rem = (off <= lim ? lim - off : 0);
778         int size = rem >> 3;
779         return new ByteBufferAsLongBuffer(this,
780                 -1,
781                 0,
782                 size,
783                 size,
784                 off,
785                 order());
786     }
787 
getFloat(long a)788     private float getFloat(long a) {
789         int x = Memory.peekInt(a, !nativeByteOrder);
790         return Float.intBitsToFloat(x);
791     }
792 
793     @Override
getFloat()794     public final float getFloat() {
795         if (!memoryRef.isAccessible) {
796             throw new IllegalStateException("buffer is inaccessible");
797         }
798         return getFloat(ix(nextGetIndex(Float.BYTES)));
799     }
800 
801     @Override
getFloat(int i)802     public final float getFloat(int i) {
803         if (!memoryRef.isAccessible) {
804             throw new IllegalStateException("buffer is inaccessible");
805         }
806         return getFloat(ix(checkIndex(i, Float.BYTES)));
807     }
808 
809     @Override
getFloatUnchecked(int i)810     final float getFloatUnchecked(int i) {
811         if (!memoryRef.isAccessible) {
812             throw new IllegalStateException("buffer is inaccessible");
813         }
814         return getFloat(ix(i));
815     }
816 
817     @Override
getUnchecked(int pos, float[] dst, int dstOffset, int length)818     final void getUnchecked(int pos, float[] dst, int dstOffset, int length) {
819         if (!memoryRef.isAccessible) {
820             throw new IllegalStateException("buffer is inaccessible");
821         }
822         Memory.peekFloatArray(ix(pos),
823                 dst, dstOffset, length, !nativeByteOrder);
824     }
825 
putFloat(long a, float x)826     private ByteBuffer putFloat(long a, float x) {
827         int y = Float.floatToRawIntBits(x);
828         Memory.pokeInt(a, y, !nativeByteOrder);
829         return this;
830     }
831 
832     @Override
putFloat(float x)833     public final ByteBuffer putFloat(float x) {
834         if (!memoryRef.isAccessible) {
835             throw new IllegalStateException("buffer is inaccessible");
836         }
837         if (isReadOnly) {
838             throw new ReadOnlyBufferException();
839         }
840         putFloat(ix(nextPutIndex(Float.BYTES)), x);
841         return this;
842     }
843 
844     @Override
putFloat(int i, float x)845     public final ByteBuffer putFloat(int i, float x) {
846         if (!memoryRef.isAccessible) {
847             throw new IllegalStateException("buffer is inaccessible");
848         }
849         if (isReadOnly) {
850             throw new ReadOnlyBufferException();
851         }
852         putFloat(ix(checkIndex(i, Float.BYTES)), x);
853         return this;
854     }
855 
856     @Override
putFloatUnchecked(int i, float x)857     final void putFloatUnchecked(int i, float x) {
858         if (!memoryRef.isAccessible) {
859             throw new IllegalStateException("buffer is inaccessible");
860         }
861         putFloat(ix(i), x);
862     }
863 
864     @Override
putUnchecked(int pos, float[] src, int srcOffset, int length)865     final void putUnchecked(int pos, float[] src, int srcOffset, int length) {
866         if (!memoryRef.isAccessible) {
867             throw new IllegalStateException("buffer is inaccessible");
868         }
869         Memory.pokeFloatArray(ix(pos),
870                 src, srcOffset, length, !nativeByteOrder);
871     }
872 
873     @Override
asFloatBuffer()874     public final FloatBuffer asFloatBuffer() {
875         if (memoryRef.isFreed) {
876             throw new IllegalStateException("buffer has been freed");
877         }
878         int off = this.position();
879         int lim = this.limit();
880         assert (off <= lim);
881         int rem = (off <= lim ? lim - off : 0);
882         int size = rem >> 2;
883         return new ByteBufferAsFloatBuffer(this,
884                 -1,
885                 0,
886                 size,
887                 size,
888                 off,
889                 order());
890     }
891 
getDouble(long a)892     private double getDouble(long a) {
893         long x = Memory.peekLong(a, !nativeByteOrder);
894         return Double.longBitsToDouble(x);
895     }
896 
897     @Override
getDouble()898     public final double getDouble() {
899         if (!memoryRef.isAccessible) {
900             throw new IllegalStateException("buffer is inaccessible");
901         }
902         return getDouble(ix(nextGetIndex(Double.BYTES)));
903     }
904 
905     @Override
getDouble(int i)906     public final double getDouble(int i) {
907         if (!memoryRef.isAccessible) {
908             throw new IllegalStateException("buffer is inaccessible");
909         }
910         return getDouble(ix(checkIndex(i, Double.BYTES)));
911     }
912 
913     @Override
getDoubleUnchecked(int i)914     final double getDoubleUnchecked(int i) {
915         if (!memoryRef.isAccessible) {
916             throw new IllegalStateException("buffer is inaccessible");
917         }
918         return getDouble(ix(i));
919     }
920 
921     @Override
getUnchecked(int pos, double[] dst, int dstOffset, int length)922     final void getUnchecked(int pos, double[] dst, int dstOffset, int length) {
923         if (!memoryRef.isAccessible) {
924             throw new IllegalStateException("buffer is inaccessible");
925         }
926         Memory.peekDoubleArray(ix(pos),
927                 dst, dstOffset, length, !nativeByteOrder);
928     }
929 
putDouble(long a, double x)930     private ByteBuffer putDouble(long a, double x) {
931         long y = Double.doubleToRawLongBits(x);
932         Memory.pokeLong(a, y, !nativeByteOrder);
933         return this;
934     }
935 
936     @Override
putDouble(double x)937     public final ByteBuffer putDouble(double x) {
938         if (!memoryRef.isAccessible) {
939             throw new IllegalStateException("buffer is inaccessible");
940         }
941         if (isReadOnly) {
942             throw new ReadOnlyBufferException();
943         }
944         putDouble(ix(nextPutIndex(Double.BYTES)), x);
945         return this;
946     }
947 
948     @Override
putDouble(int i, double x)949     public final ByteBuffer putDouble(int i, double x) {
950         if (!memoryRef.isAccessible) {
951             throw new IllegalStateException("buffer is inaccessible");
952         }
953         if (isReadOnly) {
954             throw new ReadOnlyBufferException();
955         }
956         putDouble(ix(checkIndex(i, Double.BYTES)), x);
957         return this;
958     }
959 
960     @Override
putDoubleUnchecked(int i, double x)961     final void putDoubleUnchecked(int i, double x) {
962         if (!memoryRef.isAccessible) {
963             throw new IllegalStateException("buffer is inaccessible");
964         }
965         putDouble(ix(i), x);
966     }
967 
968     @Override
putUnchecked(int pos, double[] src, int srcOffset, int length)969     final void putUnchecked(int pos, double[] src, int srcOffset, int length) {
970         if (!memoryRef.isAccessible) {
971             throw new IllegalStateException("buffer is inaccessible");
972         }
973         Memory.pokeDoubleArray(ix(pos),
974                 src, srcOffset, length, !nativeByteOrder);
975     }
976 
977     @Override
asDoubleBuffer()978     public final DoubleBuffer asDoubleBuffer() {
979         if (memoryRef.isFreed) {
980             throw new IllegalStateException("buffer has been freed");
981         }
982         int off = this.position();
983         int lim = this.limit();
984         assert (off <= lim);
985         int rem = (off <= lim ? lim - off : 0);
986 
987         int size = rem >> 3;
988         return new ByteBufferAsDoubleBuffer(this,
989                 -1,
990                 0,
991                 size,
992                 size,
993                 off,
994                 order());
995     }
996 
997     @Override
isAccessible()998     public final boolean isAccessible() {
999         return memoryRef.isAccessible;
1000     }
1001 
1002     @Override
setAccessible(boolean value)1003     public final void setAccessible(boolean value) {
1004         memoryRef.isAccessible = value;
1005     }
1006 }
1007