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