Package java.nio

Source Code of java.nio.DirectByteBuffer

/*
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You under the Apache License, Version 2.0
*  (the "License"); you may not use this file except in compliance with
*  the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/

package java.nio;

import org.apache.harmony.luni.platform.PlatformAddress;
import org.apache.harmony.luni.platform.PlatformAddressFactory;
import org.apache.harmony.nio.internal.DirectBuffer;
import org.apache.harmony.nio.internal.nls.Messages;

/**
* DirectByteBuffer, ReadWriteDirectByteBuffer and ReadOnlyDirectByteBuffer
* compose the implementation of platform memory based byte buffers.
* <p>
* DirectByteBuffer implements all the shared readonly methods and is extended
* by the other two classes.
* </p>
* <p>
* All methods are marked final for runtime performance.
* </p>
*
*/
abstract class DirectByteBuffer extends BaseByteBuffer implements DirectBuffer {

    // This is the base address of the buffer memory.
    protected PlatformAddress address;

    // This is the offset from the base address at which this buffer logically
    // starts.
    protected final int offset;

    /*
     * Constructs a new direct byte buffer of the given capacity on newly
     * allocated OS memory. The memory will have been zeroed. When the instance
     * is discarded the OS memory will be freed if it has not already been done
     * so by an explicit call to #free(). Callers are encouraged to explicitly
     * free the memory where possible.
     */
    DirectByteBuffer(int capacity) {
        this(PlatformAddressFactory.alloc(capacity, (byte) 0), capacity, 0);
        address.autoFree();
    }

    DirectByteBuffer(PlatformAddress address, int capacity, int offset) {
        super(capacity);
        this.address = address;
        this.offset = offset;
    }

    /*
     * Override ByteBuffer.get(byte[], int, int) to improve performance.
     *
     * (non-Javadoc)
     *
     * @see java.nio.ByteBuffer#get(byte[], int, int)
     */
    @Override
    public final ByteBuffer get(byte[] dest, int off, int len) {
        int length = dest.length;
        if ((off < 0) || (len < 0) || (long) off + (long) len > length) {
            throw new IndexOutOfBoundsException();
        }
        if (len > remaining()) {
            throw new BufferUnderflowException();
        }
        getBaseAddress().getByteArray(offset + position, dest, off, len);
        position += len;
        return this;
    }

    @Override
    public final byte get() {
        if (position == limit) {
            throw new BufferUnderflowException();
        }
        return getBaseAddress().getByte(offset + position++);
    }

    @Override
    public final byte get(int index) {
        if (index < 0 || index >= limit) {
            throw new IndexOutOfBoundsException();
        }
        return getBaseAddress().getByte(offset + index);
    }

    @Override
    public final double getDouble() {
        int newPosition = position + 8;
        if (newPosition > limit) {
            throw new BufferUnderflowException();
        }
        double result = getBaseAddress().getDouble(offset + position, order);
        position = newPosition;
        return result;
    }

    @Override
    public final double getDouble(int index) {
        if (index < 0 || (long) index + 8 > limit) {
            throw new IndexOutOfBoundsException();
        }
        return getBaseAddress().getDouble(offset + index, order);
    }

    @Override
    public final float getFloat() {
        int newPosition = position + 4;
        if (newPosition > limit) {
            throw new BufferUnderflowException();
        }
        float result = getBaseAddress().getFloat(offset + position, order);
        position = newPosition;
        return result;
    }

    @Override
    public final float getFloat(int index) {
        if (index < 0 || (long) index + 4 > limit) {
            throw new IndexOutOfBoundsException();
        }
        return getBaseAddress().getFloat(offset + index, order);
    }

    @Override
    public final int getInt() {
        int newPosition = position + 4;
        if (newPosition > limit) {
            throw new BufferUnderflowException();
        }
        int result = getBaseAddress().getInt(offset + position, order);
        position = newPosition;
        return result;
    }

    @Override
    public final int getInt(int index) {
        if (index < 0 || (long) index + 4 > limit) {
            throw new IndexOutOfBoundsException();
        }
        return getBaseAddress().getInt(offset + index, order);
    }

    @Override
    public final long getLong() {
        int newPosition = position + 8;
        if (newPosition > limit) {
            throw new BufferUnderflowException();
        }
        long result = getBaseAddress().getLong(offset + position, order);
        position = newPosition;
        return result;
    }

    @Override
    public final long getLong(int index) {
        if (index < 0 || (long) index + 8 > limit) {
            throw new IndexOutOfBoundsException();
        }
        return getBaseAddress().getLong(offset + index, order);
    }

    @Override
    public final short getShort() {
        int newPosition = position + 2;
        if (newPosition > limit) {
            throw new BufferUnderflowException();
        }
        short result = getBaseAddress().getShort(offset + position, order);
        position = newPosition;
        return result;
    }

    @Override
    public final short getShort(int index) {
        if (index < 0 || (long) index + 2 > limit) {
            throw new IndexOutOfBoundsException();
        }
        return getBaseAddress().getShort(offset + index, order);
    }

    @Override
    public final boolean isDirect() {
        return true;
    }

    public final boolean isAddressValid() {
        return address != PlatformAddress.INVALID;
    }

    public final void addressValidityCheck() {
        if (!isAddressValid()) {
            // nio.08=Cannot use the direct byte buffer after it has been
            // explicitly freed.
            throw new IllegalStateException(Messages.getString("nio.08")); //$NON-NLS-1$
        }
    }

    /*
     * Answers the base address of the buffer (i.e. before offset).
     */
    public final PlatformAddress getBaseAddress() {
        addressValidityCheck();
        return address;
    }

    /**
     * Answers the platform address of the start of this buffer instance.
     * <em>You must not attempt to free the returned address!!</em> It may not
     * be an address that was explicitly malloc'ed (i.e. if this buffer is the
     * result of a split); and it may be memory shared by multiple buffers.
     * <p>
     * If you can guarantee that you want to free the underlying memory call the
     * #free() method on this instance -- generally applications will rely on
     * the garbage collector to autofree this memory.
     * </p>
     *
     * @return the effective address of the start of the buffer.
     * @throws IllegalStateException
     *             if this buffer address is known to have been freed
     *             previously.
     */
    public final PlatformAddress getEffectiveAddress() {
        return getBaseAddress().offsetBytes(offset);
    }

    /**
     * Explicitly free the memory used by this direct byte buffer. If the memory
     * has already been freed then this is a no-op. Once the memory has been
     * freed then operations requiring access to the memory will throw an
     * <code>IllegalStateException</code>.
     * <p>
     * Note this is is possible that the memory is freed by code that reaches
     * into the address and explicitly frees it 'beneath' us -- this is bad
     * form.
     * </p>
     */
    public final void free() {
        if (isAddressValid()) {
            PlatformAddress a = address;
            address = PlatformAddress.INVALID;
            a.free();
        }
    }

    @Override
    final protected byte[] protectedArray() {
        throw new UnsupportedOperationException();
    }

    @Override
    final protected int protectedArrayOffset() {
        throw new UnsupportedOperationException();
    }

    @Override
    final protected boolean protectedHasArray() {
        return false;
    }

    public final int getByteCapacity() {
        return capacity;
    }
}
TOP

Related Classes of java.nio.DirectByteBuffer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.