gpt4 book ai didi

java - 如何将 native 内存复制到 DirectByteBuffer

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:42:18 24 4
gpt4 key购买 nike

我知道一种方法 - 在 C++ 端使用 memcpy:

C++ 方法:

void CopyData(void* buffer, int size)
{
memcpy(buffer, source, size);
}

JNR 映射:

void CopyData(@Pinned @Out ByteBuffer byteBuffer, @Pinned @In int size);

Java 调用:

ByteBuffer buffer = ByteBuffer.allocateDirect(size);
adapter.CopyData(buffer, size);

但我想处理 native 代码不复制数据,而只返回指向要复制的内存的指针的情况:

C++ 方法:

void* GetData1()
{
return source;
}

// or

struct Data
{
void* data;
};

void* GetData2(Data* outData)
{
outData->data = source;
}

我知道如何编写 JNR 映射以便能够将数据复制到 HeapByteBuffer:

Pointer GetData1();

// or

void GetData2(@Pinned @Out Data outData);

final class Data extends Struct {

public final Struct.Pointer data;

public DecodeResult(Runtime runtime) {
super(runtime);

data = new Struct.Pointer();
}
}

Java 调用:

ByteBuffer buffer = ByteBuffer.allocate(size);
Pointer dataPtr = adapter.GetData1();
dataPtr.get(0, buffer.array(), 0, buffer.array().length);

// or

ByteBuffer buffer = ByteBuffer.allocate(size);
Data outData = new Data(runtime);
adapter.GetData2(outData);

Pointer dataPtr = outData.data.get();
dataPtr.get(0, buffer.array(), 0, buffer.array().length);

但我还没有找到将内存复制到 DirectByteBuffer 而不是 HeapByteBuffer 的方法。上面的代码片段不适用于 DirectByteBuffer,因为 buffer.array() 对于这样的缓冲区是 null,因为它由 native 内存区域支持。

请帮忙。

最佳答案

我发现了几种将 JNR native 内存复制到 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(runtime, buffer);

第一个和第二个指针由 DirectMemoryIO 支持,但第三个指针由 ByteBufferMemoryIO 支持,它涉及缓慢的逐字节复制。

一个缺点是 DirectMemoryIO 实例非常重量级。它在 JVM 堆上分配 32 个字节,因此在大量 JNR 调用的情况下,所有 DirectMemoryIO 实例都会占用大部分内存。

关于java - 如何将 native 内存复制到 DirectByteBuffer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56332625/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com