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