Я нашел несколько способов выполнить копирование собственной памяти JNR в DirectByteBuffer
. Они отличаются по эффективности. В настоящее время я использую следующий подход, я не знаю, является ли это лучшим или предназначенным авторами JNR:
ByteBuffer buffer = ByteBuffer.allocateDirect(size);
Pointer dataPtr = adapter.GetData1();
long destAddress = ((DirectBuffer)buffer).address();
Pointer destPtr = AsmRuntime.pointerValue(destAddress, runtime);
assert dataPtr.isDirect() && destPtr.isDirect();
dataPtr.transferTo(0, destPtr, 0, size);
или
ByteBuffer buffer = ByteBuffer.allocateDirect(size);
Data outData = new Data(runtime);
adapter.GetData2(outData);
Pointer dataPtr = outData.data.get();
long destAddress = ((DirectBuffer)buffer).address();
Pointer destPtr = AsmRuntime.pointerValue(destAddress, runtime);
assert dataPtr.isDirect() && destPtr.isDirect();
dataPtr.transferTo(0, destPtr, 0, size);
Важно, чтобы вышеприведенное утверждение было выполнено. Это гарантирует, что указатели являются jnr.ffi.provider.jffi.DirectMemoryIO
экземплярами, а эффективный метод memcpy
используется для копирования (проверьте реализацию DirectMemoryIO.transferTo()
).
Альтернатива - обернуть DirectByteBuffer
, используя следующий метод:
Pointer destPtr = Pointer.wrap(runtime, destAddress);
или
Pointer destPtr = Pointer.wrap(runtime, destAddress, size);
но нет:
Pointer destPtr = Pointer.wrap (время выполнения, буфер);
Первый и второй указатели поддерживаются DirectMemoryIO
, но третий указатель поддерживается ByteBufferMemoryIO
и включает медленное побайтное копирование.
Единственным недостатком является то, что экземпляр DirectMemoryIO
довольно тяжелый. Он выделяет 32 байта в куче JVM, поэтому в случае большого количества вызовов JNR все экземпляры DirectMemoryIO
занимают большую часть памяти.