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