• 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 
slice(int pos, int lim)170     ByteBuffer slice(int pos, int lim) {
171         if (!memoryRef.isAccessible) {
172             throw new IllegalStateException("buffer is inaccessible");
173         }
174         assert (pos >= 0);
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
duplicate()183     public final ByteBuffer duplicate() {
184         if (memoryRef.isFreed) {
185             throw new IllegalStateException("buffer has been freed");
186         }
187         return new DirectByteBuffer(memoryRef,
188                 this.markValue(),
189                 this.position(),
190                 this.limit(),
191                 this.capacity(),
192                 offset,
193                 isReadOnly);
194     }
195 
196     @Override
asReadOnlyBuffer()197     public final ByteBuffer asReadOnlyBuffer() {
198         if (memoryRef.isFreed) {
199             throw new IllegalStateException("buffer has been freed");
200         }
201         return new DirectByteBuffer(memoryRef,
202                 this.markValue(),
203                 this.position(),
204                 this.limit(),
205                 this.capacity(),
206                 offset,
207                 true);
208     }
209 
210     @Override
address()211     public final long address() {
212         return address;
213     }
214 
ix(int i)215     private long ix(int i) {
216         return address + i;
217     }
218 
get(long a)219     private byte get(long a) {
220         return Memory.peekByte(a);
221     }
222 
223     @Override
get()224     public final byte get() {
225         if (!memoryRef.isAccessible) {
226             throw new IllegalStateException("buffer is inaccessible");
227         }
228         return get(ix(nextGetIndex()));
229     }
230 
231     @Override
get(int i)232     public final byte get(int i) {
233         if (!memoryRef.isAccessible) {
234             throw new IllegalStateException("buffer is inaccessible");
235         }
236         return get(ix(checkIndex(i)));
237     }
238 
239     // This method is not declared final because it is overridden in tests.
240     @Override
get(byte[] dst, int dstOffset, int length)241     public ByteBuffer get(byte[] dst, int dstOffset, int length) {
242         if (!memoryRef.isAccessible) {
243             throw new IllegalStateException("buffer is inaccessible");
244         }
245         checkBounds(dstOffset, length, dst.length);
246         int pos = position();
247         int lim = limit();
248         assert (pos <= lim);
249         int rem = (pos <= lim ? lim - pos : 0);
250         if (length > rem)
251             throw new BufferUnderflowException();
252         Memory.peekByteArray(ix(pos),
253                 dst, dstOffset, length);
254         position = pos + length;
255         return this;
256     }
257 
put(long a, byte x)258     private ByteBuffer put(long a, byte x) {
259         Memory.pokeByte(a, x);
260         return this;
261     }
262 
263     @Override
put(ByteBuffer src)264     public ByteBuffer put(ByteBuffer src) {
265         if (!memoryRef.isAccessible) {
266             throw new IllegalStateException("buffer is inaccessible");
267         }
268         return super.put(src);
269     }
270 
271     @Override
put(byte x)272     public final ByteBuffer put(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(nextPutIndex()), x);
280         return this;
281     }
282 
283     @Override
put(int i, byte x)284     public final ByteBuffer put(int i, byte x) {
285         if (!memoryRef.isAccessible) {
286             throw new IllegalStateException("buffer is inaccessible");
287         }
288         if (isReadOnly) {
289             throw new ReadOnlyBufferException();
290         }
291         put(ix(checkIndex(i)), x);
292         return this;
293     }
294 
295     // This method is not declared final because it is overridden in tests.
296     @Override
put(byte[] src, int srcOffset, int length)297     public ByteBuffer put(byte[] src, int srcOffset, int length) {
298         if (!memoryRef.isAccessible) {
299             throw new IllegalStateException("buffer is inaccessible");
300         }
301         if (isReadOnly) {
302             throw new ReadOnlyBufferException();
303         }
304         checkBounds(srcOffset, length, src.length);
305         int pos = position();
306         int lim = limit();
307         assert (pos <= lim);
308         int rem = (pos <= lim ? lim - pos : 0);
309         if (length > rem)
310             throw new BufferOverflowException();
311         Memory.pokeByteArray(ix(pos),
312                 src, srcOffset, length);
313         position = pos + length;
314         return this;
315     }
316 
317     @Override
compact()318     public final ByteBuffer compact() {
319         if (!memoryRef.isAccessible) {
320             throw new IllegalStateException("buffer is inaccessible");
321         }
322         if (isReadOnly) {
323             throw new ReadOnlyBufferException();
324         }
325         int pos = position();
326         int lim = limit();
327         assert (pos <= lim);
328         int rem = (pos <= lim ? lim - pos : 0);
329         System.arraycopy(hb, position + offset, hb, offset, remaining());
330         position(rem);
331         limit(capacity());
332         discardMark();
333         return this;
334     }
335 
336     @Override
isDirect()337     public final boolean isDirect() {
338         return true;
339     }
340 
341     @Override
isReadOnly()342     public final boolean isReadOnly() {
343         return isReadOnly;
344     }
345 
346     // Used by java.nio.Bits
347     @Override
_get(int i)348     final byte _get(int i) {                          // package-private
349         return get(i);
350     }
351 
352     // Used by java.nio.Bits
353     @Override
_put(int i, byte b)354     final void _put(int i, byte b) {                  // package-private
355         put(i, b);
356     }
357 
358     @Override
getChar()359     public final char getChar() {
360         if (!memoryRef.isAccessible) {
361             throw new IllegalStateException("buffer is inaccessible");
362         }
363         int newPosition = position + Character.BYTES;
364         if (newPosition > limit()) {
365             throw new BufferUnderflowException();
366         }
367         char x = (char) Memory.peekShort(ix(position), !nativeByteOrder);
368         position = newPosition;
369         return x;
370     }
371 
372     @Override
getChar(int i)373     public final char getChar(int i) {
374         if (!memoryRef.isAccessible) {
375             throw new IllegalStateException("buffer is inaccessible");
376         }
377         checkIndex(i, Character.BYTES);
378         return (char) Memory.peekShort(ix(i), !nativeByteOrder);
379     }
380 
381     @Override
getCharUnchecked(int i)382     char getCharUnchecked(int i) {
383         if (!memoryRef.isAccessible) {
384             throw new IllegalStateException("buffer is inaccessible");
385         }
386         return (char) Memory.peekShort(ix(i), !nativeByteOrder);
387     }
388 
389     @Override
getUnchecked(int pos, char[] dst, int dstOffset, int length)390     void getUnchecked(int pos, char[] dst, int dstOffset, int length) {
391         if (!memoryRef.isAccessible) {
392             throw new IllegalStateException("buffer is inaccessible");
393         }
394         Memory.peekCharArray(ix(pos),
395                 dst, dstOffset, length, !nativeByteOrder);
396     }
397 
putChar(long a, char x)398     private ByteBuffer putChar(long a, char x) {
399         Memory.pokeShort(a, (short) x, !nativeByteOrder);
400         return this;
401     }
402 
403     @Override
putChar(char x)404     public final ByteBuffer putChar(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(nextPutIndex(Character.BYTES)), x);
412         return this;
413     }
414 
415     @Override
putChar(int i, char x)416     public final ByteBuffer putChar(int i, char x) {
417         if (!memoryRef.isAccessible) {
418             throw new IllegalStateException("buffer is inaccessible");
419         }
420         if (isReadOnly) {
421             throw new ReadOnlyBufferException();
422         }
423         putChar(ix(checkIndex(i, Character.BYTES)), x);
424         return this;
425     }
426 
427     @Override
putCharUnchecked(int i, char x)428     void putCharUnchecked(int i, char x) {
429         if (!memoryRef.isAccessible) {
430             throw new IllegalStateException("buffer is inaccessible");
431         }
432         putChar(ix(i), x);
433     }
434 
435     @Override
putUnchecked(int pos, char[] src, int srcOffset, int length)436     void putUnchecked(int pos, char[] src, int srcOffset, int length) {
437         if (!memoryRef.isAccessible) {
438             throw new IllegalStateException("buffer is inaccessible");
439         }
440         Memory.pokeCharArray(ix(pos),
441                 src, srcOffset, length, !nativeByteOrder);
442     }
443 
444     @Override
asCharBuffer()445     public final CharBuffer asCharBuffer() {
446         if (memoryRef.isFreed) {
447             throw new IllegalStateException("buffer has been freed");
448         }
449         int off = this.position();
450         int lim = this.limit();
451         assert (off <= lim);
452         int rem = (off <= lim ? lim - off : 0);
453         int size = rem >> 1;
454         return new ByteBufferAsCharBuffer(this,
455                 -1,
456                 0,
457                 size,
458                 size,
459                 off,
460                 order());
461     }
462 
getShort(long a)463     private short getShort(long a) {
464         return Memory.peekShort(a, !nativeByteOrder);
465     }
466 
467     @Override
getShort()468     public final short getShort() {
469         if (!memoryRef.isAccessible) {
470             throw new IllegalStateException("buffer is inaccessible");
471         }
472         return getShort(ix(nextGetIndex(Short.BYTES)));
473     }
474 
475     @Override
getShort(int i)476     public final short getShort(int i) {
477         if (!memoryRef.isAccessible) {
478             throw new IllegalStateException("buffer is inaccessible");
479         }
480         return getShort(ix(checkIndex(i, Short.BYTES)));
481     }
482 
483     @Override
getShortUnchecked(int i)484     short getShortUnchecked(int i) {
485         if (!memoryRef.isAccessible) {
486             throw new IllegalStateException("buffer is inaccessible");
487         }
488         return getShort(ix(i));
489     }
490 
491     @Override
getUnchecked(int pos, short[] dst, int dstOffset, int length)492     void getUnchecked(int pos, short[] dst, int dstOffset, int length) {
493         if (!memoryRef.isAccessible) {
494             throw new IllegalStateException("buffer is inaccessible");
495         }
496         Memory.peekShortArray(ix(pos),
497                 dst, dstOffset, length, !nativeByteOrder);
498     }
499 
putShort(long a, short x)500     private ByteBuffer putShort(long a, short x) {
501         Memory.pokeShort(a, x, !nativeByteOrder);
502         return this;
503     }
504 
505     @Override
putShort(short x)506     public final ByteBuffer putShort(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(nextPutIndex(Short.BYTES)), x);
514         return this;
515     }
516 
517     @Override
putShort(int i, short x)518     public final ByteBuffer putShort(int i, short x) {
519         if (!memoryRef.isAccessible) {
520             throw new IllegalStateException("buffer is inaccessible");
521         }
522         if (isReadOnly) {
523             throw new ReadOnlyBufferException();
524         }
525         putShort(ix(checkIndex(i, Short.BYTES)), x);
526         return this;
527     }
528 
529     @Override
putShortUnchecked(int i, short x)530     void putShortUnchecked(int i, short x) {
531         if (!memoryRef.isAccessible) {
532             throw new IllegalStateException("buffer is inaccessible");
533         }
534         putShort(ix(i), x);
535     }
536 
537     @Override
putUnchecked(int pos, short[] src, int srcOffset, int length)538     void putUnchecked(int pos, short[] src, int srcOffset, int length) {
539         if (!memoryRef.isAccessible) {
540             throw new IllegalStateException("buffer is inaccessible");
541         }
542         Memory.pokeShortArray(ix(pos),
543                 src, srcOffset, length, !nativeByteOrder);
544     }
545 
546     @Override
asShortBuffer()547     public final ShortBuffer asShortBuffer() {
548         if (memoryRef.isFreed) {
549             throw new IllegalStateException("buffer has been freed");
550         }
551         int off = this.position();
552         int lim = this.limit();
553         assert (off <= lim);
554         int rem = (off <= lim ? lim - off : 0);
555         int size = rem >> 1;
556         return new ByteBufferAsShortBuffer(this,
557                 -1,
558                 0,
559                 size,
560                 size,
561                 off,
562                 order());
563     }
564 
getInt(long a)565     private int getInt(long a) {
566         return Memory.peekInt(a, !nativeByteOrder);
567     }
568 
569     @Override
getInt()570     public int getInt() {
571         if (!memoryRef.isAccessible) {
572             throw new IllegalStateException("buffer is inaccessible");
573         }
574         return getInt(ix(nextGetIndex(Integer.BYTES)));
575     }
576 
577     @Override
getInt(int i)578     public int getInt(int i) {
579         if (!memoryRef.isAccessible) {
580             throw new IllegalStateException("buffer is inaccessible");
581         }
582         return getInt(ix(checkIndex(i, (Integer.BYTES))));
583     }
584 
585     @Override
getIntUnchecked(int i)586     final int getIntUnchecked(int i) {
587         if (!memoryRef.isAccessible) {
588             throw new IllegalStateException("buffer is inaccessible");
589         }
590         return getInt(ix(i));
591     }
592 
593     @Override
getUnchecked(int pos, int[] dst, int dstOffset, int length)594     final void getUnchecked(int pos, int[] dst, int dstOffset, int length) {
595         if (!memoryRef.isAccessible) {
596             throw new IllegalStateException("buffer is inaccessible");
597         }
598         Memory.peekIntArray(ix(pos),
599                 dst, dstOffset, length, !nativeByteOrder);
600     }
601 
putInt(long a, int x)602     private ByteBuffer putInt(long a, int x) {
603         Memory.pokeInt(a, x, !nativeByteOrder);
604         return this;
605     }
606 
607     @Override
putInt(int x)608     public final ByteBuffer putInt(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(nextPutIndex(Integer.BYTES)), x);
616         return this;
617     }
618 
619     @Override
putInt(int i, int x)620     public final ByteBuffer putInt(int i, int x) {
621         if (!memoryRef.isAccessible) {
622             throw new IllegalStateException("buffer is inaccessible");
623         }
624         if (isReadOnly) {
625             throw new ReadOnlyBufferException();
626         }
627         putInt(ix(checkIndex(i, Integer.BYTES)), x);
628         return this;
629     }
630 
631     @Override
putIntUnchecked(int i, int x)632     final void putIntUnchecked(int i, int x) {
633         if (!memoryRef.isAccessible) {
634             throw new IllegalStateException("buffer is inaccessible");
635         }
636         putInt(ix(i), x);
637     }
638 
639     @Override
putUnchecked(int pos, int[] src, int srcOffset, int length)640     final void putUnchecked(int pos, int[] src, int srcOffset, int length) {
641         if (!memoryRef.isAccessible) {
642             throw new IllegalStateException("buffer is inaccessible");
643         }
644         Memory.pokeIntArray(ix(pos),
645                 src, srcOffset, length, !nativeByteOrder);
646     }
647 
648     @Override
asIntBuffer()649     public final IntBuffer asIntBuffer() {
650         if (memoryRef.isFreed) {
651             throw new IllegalStateException("buffer has been freed");
652         }
653         int off = this.position();
654         int lim = this.limit();
655         assert (off <= lim);
656         int rem = (off <= lim ? lim - off : 0);
657         int size = rem >> 2;
658         return new ByteBufferAsIntBuffer(this,
659                 -1,
660                 0,
661                 size,
662                 size,
663                 off,
664                 order());
665     }
666 
getLong(long a)667     private long getLong(long a) {
668         return Memory.peekLong(a, !nativeByteOrder);
669     }
670 
671     @Override
getLong()672     public final long getLong() {
673         if (!memoryRef.isAccessible) {
674             throw new IllegalStateException("buffer is inaccessible");
675         }
676         return getLong(ix(nextGetIndex(Long.BYTES)));
677     }
678 
679     @Override
getLong(int i)680     public final long getLong(int i) {
681         if (!memoryRef.isAccessible) {
682             throw new IllegalStateException("buffer is inaccessible");
683         }
684         return getLong(ix(checkIndex(i, Long.BYTES)));
685     }
686 
687     @Override
getLongUnchecked(int i)688     final long getLongUnchecked(int i) {
689         if (!memoryRef.isAccessible) {
690             throw new IllegalStateException("buffer is inaccessible");
691         }
692         return getLong(ix(i));
693     }
694 
695     @Override
getUnchecked(int pos, long[] dst, int dstOffset, int length)696     final void getUnchecked(int pos, long[] dst, int dstOffset, int length) {
697         if (!memoryRef.isAccessible) {
698             throw new IllegalStateException("buffer is inaccessible");
699         }
700         Memory.peekLongArray(ix(pos),
701                 dst, dstOffset, length, !nativeByteOrder);
702     }
703 
putLong(long a, long x)704     private ByteBuffer putLong(long a, long x) {
705         Memory.pokeLong(a, x, !nativeByteOrder);
706         return this;
707     }
708 
709     @Override
putLong(long x)710     public final ByteBuffer putLong(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(nextPutIndex(Long.BYTES)), x);
718         return this;
719     }
720 
721     @Override
putLong(int i, long x)722     public final ByteBuffer putLong(int i, long x) {
723         if (!memoryRef.isAccessible) {
724             throw new IllegalStateException("buffer is inaccessible");
725         }
726         if (isReadOnly) {
727             throw new ReadOnlyBufferException();
728         }
729         putLong(ix(checkIndex(i, Long.BYTES)), x);
730         return this;
731     }
732 
733     @Override
putLongUnchecked(int i, long x)734     final void putLongUnchecked(int i, long x) {
735         if (!memoryRef.isAccessible) {
736             throw new IllegalStateException("buffer is inaccessible");
737         }
738         putLong(ix(i), x);
739     }
740 
741     @Override
putUnchecked(int pos, long[] src, int srcOffset, int length)742     final void putUnchecked(int pos, long[] src, int srcOffset, int length) {
743         if (!memoryRef.isAccessible) {
744             throw new IllegalStateException("buffer is inaccessible");
745         }
746         Memory.pokeLongArray(ix(pos),
747                 src, srcOffset, length, !nativeByteOrder);
748     }
749 
750     @Override
asLongBuffer()751     public final LongBuffer asLongBuffer() {
752         if (memoryRef.isFreed) {
753             throw new IllegalStateException("buffer has been freed");
754         }
755         int off = this.position();
756         int lim = this.limit();
757         assert (off <= lim);
758         int rem = (off <= lim ? lim - off : 0);
759         int size = rem >> 3;
760         return new ByteBufferAsLongBuffer(this,
761                 -1,
762                 0,
763                 size,
764                 size,
765                 off,
766                 order());
767     }
768 
getFloat(long a)769     private float getFloat(long a) {
770         int x = Memory.peekInt(a, !nativeByteOrder);
771         return Float.intBitsToFloat(x);
772     }
773 
774     @Override
getFloat()775     public final float getFloat() {
776         if (!memoryRef.isAccessible) {
777             throw new IllegalStateException("buffer is inaccessible");
778         }
779         return getFloat(ix(nextGetIndex(Float.BYTES)));
780     }
781 
782     @Override
getFloat(int i)783     public final float getFloat(int i) {
784         if (!memoryRef.isAccessible) {
785             throw new IllegalStateException("buffer is inaccessible");
786         }
787         return getFloat(ix(checkIndex(i, Float.BYTES)));
788     }
789 
790     @Override
getFloatUnchecked(int i)791     final float getFloatUnchecked(int i) {
792         if (!memoryRef.isAccessible) {
793             throw new IllegalStateException("buffer is inaccessible");
794         }
795         return getFloat(ix(i));
796     }
797 
798     @Override
getUnchecked(int pos, float[] dst, int dstOffset, int length)799     final void getUnchecked(int pos, float[] dst, int dstOffset, int length) {
800         if (!memoryRef.isAccessible) {
801             throw new IllegalStateException("buffer is inaccessible");
802         }
803         Memory.peekFloatArray(ix(pos),
804                 dst, dstOffset, length, !nativeByteOrder);
805     }
806 
putFloat(long a, float x)807     private ByteBuffer putFloat(long a, float x) {
808         int y = Float.floatToRawIntBits(x);
809         Memory.pokeInt(a, y, !nativeByteOrder);
810         return this;
811     }
812 
813     @Override
putFloat(float x)814     public final ByteBuffer putFloat(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(nextPutIndex(Float.BYTES)), x);
822         return this;
823     }
824 
825     @Override
putFloat(int i, float x)826     public final ByteBuffer putFloat(int i, float x) {
827         if (!memoryRef.isAccessible) {
828             throw new IllegalStateException("buffer is inaccessible");
829         }
830         if (isReadOnly) {
831             throw new ReadOnlyBufferException();
832         }
833         putFloat(ix(checkIndex(i, Float.BYTES)), x);
834         return this;
835     }
836 
837     @Override
putFloatUnchecked(int i, float x)838     final void putFloatUnchecked(int i, float x) {
839         if (!memoryRef.isAccessible) {
840             throw new IllegalStateException("buffer is inaccessible");
841         }
842         putFloat(ix(i), x);
843     }
844 
845     @Override
putUnchecked(int pos, float[] src, int srcOffset, int length)846     final void putUnchecked(int pos, float[] src, int srcOffset, int length) {
847         if (!memoryRef.isAccessible) {
848             throw new IllegalStateException("buffer is inaccessible");
849         }
850         Memory.pokeFloatArray(ix(pos),
851                 src, srcOffset, length, !nativeByteOrder);
852     }
853 
854     @Override
asFloatBuffer()855     public final FloatBuffer asFloatBuffer() {
856         if (memoryRef.isFreed) {
857             throw new IllegalStateException("buffer has been freed");
858         }
859         int off = this.position();
860         int lim = this.limit();
861         assert (off <= lim);
862         int rem = (off <= lim ? lim - off : 0);
863         int size = rem >> 2;
864         return new ByteBufferAsFloatBuffer(this,
865                 -1,
866                 0,
867                 size,
868                 size,
869                 off,
870                 order());
871     }
872 
getDouble(long a)873     private double getDouble(long a) {
874         long x = Memory.peekLong(a, !nativeByteOrder);
875         return Double.longBitsToDouble(x);
876     }
877 
878     @Override
getDouble()879     public final double getDouble() {
880         if (!memoryRef.isAccessible) {
881             throw new IllegalStateException("buffer is inaccessible");
882         }
883         return getDouble(ix(nextGetIndex(Double.BYTES)));
884     }
885 
886     @Override
getDouble(int i)887     public final double getDouble(int i) {
888         if (!memoryRef.isAccessible) {
889             throw new IllegalStateException("buffer is inaccessible");
890         }
891         return getDouble(ix(checkIndex(i, Double.BYTES)));
892     }
893 
894     @Override
getDoubleUnchecked(int i)895     final double getDoubleUnchecked(int i) {
896         if (!memoryRef.isAccessible) {
897             throw new IllegalStateException("buffer is inaccessible");
898         }
899         return getDouble(ix(i));
900     }
901 
902     @Override
getUnchecked(int pos, double[] dst, int dstOffset, int length)903     final void getUnchecked(int pos, double[] dst, int dstOffset, int length) {
904         if (!memoryRef.isAccessible) {
905             throw new IllegalStateException("buffer is inaccessible");
906         }
907         Memory.peekDoubleArray(ix(pos),
908                 dst, dstOffset, length, !nativeByteOrder);
909     }
910 
putDouble(long a, double x)911     private ByteBuffer putDouble(long a, double x) {
912         long y = Double.doubleToRawLongBits(x);
913         Memory.pokeLong(a, y, !nativeByteOrder);
914         return this;
915     }
916 
917     @Override
putDouble(double x)918     public final ByteBuffer putDouble(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(nextPutIndex(Double.BYTES)), x);
926         return this;
927     }
928 
929     @Override
putDouble(int i, double x)930     public final ByteBuffer putDouble(int i, double x) {
931         if (!memoryRef.isAccessible) {
932             throw new IllegalStateException("buffer is inaccessible");
933         }
934         if (isReadOnly) {
935             throw new ReadOnlyBufferException();
936         }
937         putDouble(ix(checkIndex(i, Double.BYTES)), x);
938         return this;
939     }
940 
941     @Override
putDoubleUnchecked(int i, double x)942     final void putDoubleUnchecked(int i, double x) {
943         if (!memoryRef.isAccessible) {
944             throw new IllegalStateException("buffer is inaccessible");
945         }
946         putDouble(ix(i), x);
947     }
948 
949     @Override
putUnchecked(int pos, double[] src, int srcOffset, int length)950     final void putUnchecked(int pos, double[] src, int srcOffset, int length) {
951         if (!memoryRef.isAccessible) {
952             throw new IllegalStateException("buffer is inaccessible");
953         }
954         Memory.pokeDoubleArray(ix(pos),
955                 src, srcOffset, length, !nativeByteOrder);
956     }
957 
958     @Override
asDoubleBuffer()959     public final DoubleBuffer asDoubleBuffer() {
960         if (memoryRef.isFreed) {
961             throw new IllegalStateException("buffer has been freed");
962         }
963         int off = this.position();
964         int lim = this.limit();
965         assert (off <= lim);
966         int rem = (off <= lim ? lim - off : 0);
967 
968         int size = rem >> 3;
969         return new ByteBufferAsDoubleBuffer(this,
970                 -1,
971                 0,
972                 size,
973                 size,
974                 off,
975                 order());
976     }
977 
978     @Override
isAccessible()979     public final boolean isAccessible() {
980         return memoryRef.isAccessible;
981     }
982 
983     @Override
setAccessible(boolean value)984     public final void setAccessible(boolean value) {
985         memoryRef.isAccessible = value;
986     }
987 }
988