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