private final static Unsafe unsafe;
private static long addressOffset;
private static long positionOffset;
private static long limitOffset;
private static long capacityOffset;
public static final long WORD_SIZE_BITS, HEADER_SIZE;
public static final long BYTE_ARRAY_BASE_OFFSET;
public static final long SHORT_ARRAY_BASE_OFFSET;
public static final long INT_ARRAY_BASE_OFFSET;
public static final long LONG_ARRAY_BASE_OFFSET;
public static final long FLOAT_ARRAY_BASE_OFFSET;
public static final long DOUBLE_ARRAY_BASE_OFFSET;
public static final long OBJECT_ARRAY_BASE_OFFSET;
private static final Object[] holder = new Object[1];
static
{
try
{
ByteBuffer buffer = ByteBuffer.allocateDirect(1);
Field unsafeField = buffer.getClass().getDeclaredField("unsafe");
unsafeField.setAccessible(true);
unsafe = (Unsafe) unsafeField.get(buffer);
unsafeField.setAccessible(false);
addressOffset = getObjectFieldOffset(buffer, "address");
positionOffset = getObjectFieldOffset(buffer, "position");
limitOffset = getObjectFieldOffset(buffer, "limit");
capacityOffset = getObjectFieldOffset(buffer, "capacity");
buffer.flip();
buffer = null;
}
catch (Exception exc)
{
exc.printStackTrace();
throw new InternalError();
}
WORD_SIZE_BITS = unsafe.addressSize() * 8;
if (WORD_SIZE_BITS != 32 && WORD_SIZE_BITS != 64)
throw new IllegalStateException("WORD_SIZE: " + WORD_SIZE_BITS);
HEADER_SIZE = WORD_SIZE_BITS / 8 * 2;
BYTE_ARRAY_BASE_OFFSET = unsafe.arrayBaseOffset(new byte[4].getClass());
SHORT_ARRAY_BASE_OFFSET = unsafe.arrayBaseOffset(new short[4].getClass());
INT_ARRAY_BASE_OFFSET = unsafe.arrayBaseOffset(new int[4].getClass());
LONG_ARRAY_BASE_OFFSET = unsafe.arrayBaseOffset(new long[4].getClass());
FLOAT_ARRAY_BASE_OFFSET = unsafe.arrayBaseOffset(new float[4].getClass());
DOUBLE_ARRAY_BASE_OFFSET = unsafe.arrayBaseOffset(new double[4].getClass());
OBJECT_ARRAY_BASE_OFFSET = unsafe.arrayBaseOffset(new Object[4].getClass());
}
public static final long getObjectAddress(Object obj)
{
holder[0] = obj;
if (WORD_SIZE_BITS == 32)
return unsafe.getInt(holder, OBJECT_ARRAY_BASE_OFFSET);
if (WORD_SIZE_BITS == 64)
return unsafe.getLong(holder, OBJECT_ARRAY_BASE_OFFSET);
throw new IllegalStateException();
}
public static final Object getObjectAtAddress(long addr)
{
if (WORD_SIZE_BITS == 32)
unsafe.putInt(holder, OBJECT_ARRAY_BASE_OFFSET, (int) (addr & 0xFFFFFFFF));
if (WORD_SIZE_BITS == 64)
unsafe.putLong(holder, OBJECT_ARRAY_BASE_OFFSET, addr);
return holder[0];
}
public static final FloatBuffer createFloatBufferAt(long pntr, int len)
{
Native.zeroOut(pntr, len << 2);
FloatBuffer buf = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asFloatBuffer();
NativeHacks.setBufferProperties(buf, pntr, 0, len, len);
buf.clear();
return buf;
}
public static final float[] createFloatArrayAt(long pntr, int len)
{
NativeHacks.copyObjectHeaderTo(new float[0], pntr);
// write length
unsafe.putInt(pntr + HEADER_SIZE, len);
return (float[]) NativeHacks.fakePointerAsObject(pntr);
}
public static final void copyObjectHeaderTo(Object obj, long pntr)
{
for (int i = 0; i < HEADER_SIZE; i++)
unsafe.putByte(pntr + i, unsafe.getByte(obj, (long) i));
}
public static final Object fakePointerAsObject(long addr)
{
if (WORD_SIZE_BITS == 32)
unsafe.putInt(holder, OBJECT_ARRAY_BASE_OFFSET, (int) (addr & 0xFFFFFFFF));
else if (WORD_SIZE_BITS == 64)
unsafe.putLong(holder, OBJECT_ARRAY_BASE_OFFSET, addr);
else
throw new IllegalStateException();
return holder[0];
}
2009-08-30
Unsafe :: Pointers
Subscribe to:
Post Comments (Atom)

No comments:
Post a Comment