как получить прямой байтовый буфер из адреса - PullRequest
0 голосов
/ 03 октября 2018

В в этом примере opencv объект Mat имеет поле nativeObj, возвращающее long, который представляет адрес объекта (то есть 140398889556640).Поскольку размер данных в пределах объекта известен, я хочу получить доступ к содержимому объекта Mat напрямую, возвращая байтовый буфер.

Каков наилучший способ сделать это?

Ответы [ 3 ]

0 голосов
/ 04 октября 2018

Если вы не хотите использовать Unsafe и хотите что-то, что работает без предупреждений в Java 9 и действительно переносимо между JVM, вы можете использовать JNI NewDirectByteBuffer .Это API, и он гарантированно будет работать.

Однако вам нужно будет написать некоторый код на C (или C ++) и отправить собственную библиотеку с вашим кодом.

0 голосов
/ 04 октября 2018

Существует крошечный фреймворк под названием «nalloc», который предназначен для помощи разработчику в манипуляциях с памятью / указателями, он может быть полезен для любых целей, для которых вы ищете прямой доступ к адресу памяти.

Кроме того, это дает вам возможность написать программу на Java в стиле C, выполняя операции с памятью вручную.

Проверьте это: https://github.com/alaisi/nalloc

0 голосов
/ 03 октября 2018

Вы можете обернуть адрес с помощью DirectByteBuffer или использовать Unsafe.

Хотя вы можете сделать это, вы, вероятно, не должны.Сначала я бы изучил все другие варианты.

// 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;
}
...