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