0N/A/*
2362N/A * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/*
0N/A */
0N/A
0N/Apackage sun.nio.ch; // Formerly in sun.misc
0N/A
0N/Aimport java.nio.ByteOrder;
0N/Aimport sun.misc.Unsafe;
0N/A
0N/A
0N/A// ## In the fullness of time, this class will be eliminated
0N/A
0N/A/**
0N/A * Proxies for objects that reside in native memory.
0N/A */
0N/A
0N/Aclass NativeObject { // package-private
0N/A
0N/A protected static final Unsafe unsafe = Unsafe.getUnsafe();
0N/A
0N/A // Native allocation address;
0N/A // may be smaller than the base address due to page-size rounding
0N/A //
0N/A protected long allocationAddress;
0N/A
0N/A // Native base address
0N/A //
0N/A private final long address;
0N/A
0N/A /**
0N/A * Creates a new native object that is based at the given native address.
0N/A */
0N/A NativeObject(long address) {
0N/A this.allocationAddress = address;
0N/A this.address = address;
0N/A }
0N/A
0N/A /**
0N/A * Creates a new native object allocated at the given native address but
0N/A * whose base is at the additional offset.
0N/A */
0N/A NativeObject(long address, long offset) {
0N/A this.allocationAddress = address;
0N/A this.address = address + offset;
0N/A }
0N/A
0N/A // Invoked only by AllocatedNativeObject
0N/A //
0N/A protected NativeObject(int size, boolean pageAligned) {
0N/A if (!pageAligned) {
0N/A this.allocationAddress = unsafe.allocateMemory(size);
0N/A this.address = this.allocationAddress;
0N/A } else {
0N/A int ps = pageSize();
0N/A long a = unsafe.allocateMemory(size + ps);
0N/A this.allocationAddress = a;
0N/A this.address = a + ps - (a & (ps - 1));
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns the native base address of this native object.
0N/A *
0N/A * @return The native base address
0N/A */
0N/A long address() {
0N/A return address;
0N/A }
0N/A
0N/A long allocationAddress() {
0N/A return allocationAddress;
0N/A }
0N/A
0N/A /**
0N/A * Creates a new native object starting at the given offset from the base
0N/A * of this native object.
0N/A *
0N/A * @param offset
0N/A * The offset from the base of this native object that is to be
0N/A * the base of the new native object
0N/A *
0N/A * @return The newly created native object
0N/A */
0N/A NativeObject subObject(int offset) {
0N/A return new NativeObject(offset + address);
0N/A }
0N/A
0N/A /**
0N/A * Reads an address from this native object at the given offset and
0N/A * constructs a native object using that address.
0N/A *
0N/A * @param offset
0N/A * The offset of the address to be read. Note that the size of an
0N/A * address is implementation-dependent.
0N/A *
0N/A * @return The native object created using the address read from the
0N/A * given offset
0N/A */
0N/A NativeObject getObject(int offset) {
0N/A long newAddress = 0L;
0N/A switch (addressSize()) {
0N/A case 8:
0N/A newAddress = unsafe.getLong(offset + address);
0N/A break;
0N/A case 4:
0N/A newAddress = unsafe.getInt(offset + address) & 0x00000000FFFFFFFF;
0N/A break;
0N/A default:
0N/A throw new InternalError("Address size not supported");
0N/A }
0N/A
0N/A return new NativeObject(newAddress);
0N/A }
0N/A
0N/A /**
0N/A * Writes the base address of the given native object at the given offset
0N/A * of this native object.
0N/A *
0N/A * @param offset
0N/A * The offset at which the address is to be written. Note that the
0N/A * size of an address is implementation-dependent.
0N/A *
0N/A * @param ob
0N/A * The native object whose address is to be written
0N/A */
0N/A void putObject(int offset, NativeObject ob) {
0N/A switch (addressSize()) {
0N/A case 8:
0N/A putLong(offset, ob.address);
0N/A break;
0N/A case 4:
0N/A putInt(offset, (int)(ob.address & 0x00000000FFFFFFFF));
0N/A break;
0N/A default:
0N/A throw new InternalError("Address size not supported");
0N/A }
0N/A }
0N/A
0N/A
0N/A /* -- Value accessors: No range checking! -- */
0N/A
0N/A /**
0N/A * Reads a byte starting at the given offset from base of this native
0N/A * object.
0N/A *
0N/A * @param offset
0N/A * The offset at which to read the byte
0N/A *
0N/A * @return The byte value read
0N/A */
0N/A final byte getByte(int offset) {
0N/A return unsafe.getByte(offset + address);
0N/A }
0N/A
0N/A /**
0N/A * Writes a byte at the specified offset from this native object's
0N/A * base address.
0N/A *
0N/A * @param offset
0N/A * The offset at which to write the byte
0N/A *
0N/A * @param value
0N/A * The byte value to be written
0N/A */
0N/A final void putByte(int offset, byte value) {
0N/A unsafe.putByte(offset + address, value);
0N/A }
0N/A
0N/A /**
0N/A * Reads a short starting at the given offset from base of this native
0N/A * object.
0N/A *
0N/A * @param offset
0N/A * The offset at which to read the short
0N/A *
0N/A * @return The short value read
0N/A */
0N/A final short getShort(int offset) {
0N/A return unsafe.getShort(offset + address);
0N/A }
0N/A
0N/A /**
0N/A * Writes a short at the specified offset from this native object's
0N/A * base address.
0N/A *
0N/A * @param offset
0N/A * The offset at which to write the short
0N/A *
0N/A * @param value
0N/A * The short value to be written
0N/A */
0N/A final void putShort(int offset, short value) {
0N/A unsafe.putShort(offset + address, value);
0N/A }
0N/A
0N/A /**
0N/A * Reads a char starting at the given offset from base of this native
0N/A * object.
0N/A *
0N/A * @param offset
0N/A * The offset at which to read the char
0N/A *
0N/A * @return The char value read
0N/A */
0N/A final char getChar(int offset) {
0N/A return unsafe.getChar(offset + address);
0N/A }
0N/A
0N/A /**
0N/A * Writes a char at the specified offset from this native object's
0N/A * base address.
0N/A *
0N/A * @param offset
0N/A * The offset at which to write the char
0N/A *
0N/A * @param value
0N/A * The char value to be written
0N/A */
0N/A final void putChar(int offset, char value) {
0N/A unsafe.putChar(offset + address, value);
0N/A }
0N/A
0N/A /**
0N/A * Reads an int starting at the given offset from base of this native
0N/A * object.
0N/A *
0N/A * @param offset
0N/A * The offset at which to read the int
0N/A *
0N/A * @return The int value read
0N/A */
0N/A final int getInt(int offset) {
0N/A return unsafe.getInt(offset + address);
0N/A }
0N/A
0N/A /**
0N/A * Writes an int at the specified offset from this native object's
0N/A * base address.
0N/A *
0N/A * @param offset
0N/A * The offset at which to write the int
0N/A *
0N/A * @param value
0N/A * The int value to be written
0N/A */
0N/A final void putInt(int offset, int value) {
0N/A unsafe.putInt(offset + address, value);
0N/A }
0N/A
0N/A /**
0N/A * Reads a long starting at the given offset from base of this native
0N/A * object.
0N/A *
0N/A * @param offset
0N/A * The offset at which to read the long
0N/A *
0N/A * @return The long value read
0N/A */
0N/A final long getLong(int offset) {
0N/A return unsafe.getLong(offset + address);
0N/A }
0N/A
0N/A /**
0N/A * Writes a long at the specified offset from this native object's
0N/A * base address.
0N/A *
0N/A * @param offset
0N/A * The offset at which to write the long
0N/A *
0N/A * @param value
0N/A * The long value to be written
0N/A */
0N/A final void putLong(int offset, long value) {
0N/A unsafe.putLong(offset + address, value);
0N/A }
0N/A
0N/A /**
0N/A * Reads a float starting at the given offset from base of this native
0N/A * object.
0N/A *
0N/A * @param offset
0N/A * The offset at which to read the float
0N/A *
0N/A * @return The float value read
0N/A */
0N/A final float getFloat(int offset) {
0N/A return unsafe.getFloat(offset + address);
0N/A }
0N/A
0N/A /**
0N/A * Writes a float at the specified offset from this native object's
0N/A * base address.
0N/A *
0N/A * @param offset
0N/A * The offset at which to write the float
0N/A *
0N/A * @param value
0N/A * The float value to be written
0N/A */
0N/A final void putFloat(int offset, float value) {
0N/A unsafe.putFloat(offset + address, value);
0N/A }
0N/A
0N/A /**
0N/A * Reads a double starting at the given offset from base of this native
0N/A * object.
0N/A *
0N/A * @param offset
0N/A * The offset at which to read the double
0N/A *
0N/A * @return The double value read
0N/A */
0N/A final double getDouble(int offset) {
0N/A return unsafe.getDouble(offset + address);
0N/A }
0N/A
0N/A /**
0N/A * Writes a double at the specified offset from this native object's
0N/A * base address.
0N/A *
0N/A * @param offset
0N/A * The offset at which to write the double
0N/A *
0N/A * @param value
0N/A * The double value to be written
0N/A */
0N/A final void putDouble(int offset, double value) {
0N/A unsafe.putDouble(offset + address, value);
0N/A }
0N/A
0N/A /**
0N/A * Returns the native architecture's address size in bytes.
0N/A *
0N/A * @return The address size of the native architecture
0N/A */
0N/A static int addressSize() {
0N/A return unsafe.addressSize();
0N/A }
0N/A
0N/A // Cache for byte order
0N/A private static ByteOrder byteOrder = null;
0N/A
0N/A /**
0N/A * Returns the byte order of the underlying hardware.
0N/A *
0N/A * @return An instance of {@link java.nio.ByteOrder}
0N/A */
0N/A static ByteOrder byteOrder() {
0N/A if (byteOrder != null)
0N/A return byteOrder;
0N/A long a = unsafe.allocateMemory(8);
0N/A try {
0N/A unsafe.putLong(a, 0x0102030405060708L);
0N/A byte b = unsafe.getByte(a);
0N/A switch (b) {
0N/A case 0x01: byteOrder = ByteOrder.BIG_ENDIAN; break;
0N/A case 0x08: byteOrder = ByteOrder.LITTLE_ENDIAN; break;
0N/A default:
0N/A assert false;
0N/A }
0N/A } finally {
0N/A unsafe.freeMemory(a);
0N/A }
0N/A return byteOrder;
0N/A }
0N/A
0N/A // Cache for page size
0N/A private static int pageSize = -1;
0N/A
0N/A /**
0N/A * Returns the page size of the underlying hardware.
0N/A *
0N/A * @return The page size, in bytes
0N/A */
0N/A static int pageSize() {
0N/A if (pageSize == -1)
0N/A pageSize = unsafe.pageSize();
0N/A return pageSize;
0N/A }
0N/A
0N/A}