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