Search code examples
javaopencvbytebufferunsafe

how to get a direct byte buffer from an address location


In this opencv example, the Mat object has a nativeObj field, returning a long that represents the address of the object (i.e 140398889556640). Because the size of the data within the object is known, I wish to access the contents of the Mat object directly, returning a byte buffer.

What is the best way to do so?


Solution

  • You can wrap the address with a DirectByteBuffer or use Unsafe.

    While you can do this, you probably shouldn't. I would explore all other options first.

    // Warning: only do this if there is no better option
    
    public static void main(String[] args) {
        ByteBuffer bb = ByteBuffer.allocateDirect(128);
        long addr = ((DirectBuffer) bb).address();
    
        ByteBuffer bb2 = wrapAddress(addr, bb.capacity());
    
        bb.putLong(0, 0x12345678);
        System.out.println(Long.toHexString(bb2.getLong(0)));
    }
    
    static final Field address, capacity;
    static {
        try {
            address = Buffer.class.getDeclaredField("address");
            address.setAccessible(true);
            capacity = Buffer.class.getDeclaredField("capacity");
            capacity.setAccessible(true);
    
        } catch (NoSuchFieldException e) {
            throw new AssertionError(e);
        }
    }
    
    public static ByteBuffer wrapAddress(long addr, int length) {
        ByteBuffer bb = ByteBuffer.allocateDirect(0).order(ByteOrder.nativeOrder());
        try {
            address.setLong(bb, addr);
            capacity.setInt(bb, length);
            bb.clear();
        } catch (IllegalAccessException e) {
            throw new AssertionError(e);
        }
        return bb;
    }