将本机指针存储在Java对象中的"正确"方法是什么?

Dan*_*idy 24 java java-native-interface

将本机指针存储在Java对象中的"正确"方法是什么?

我可以将指针视为Java int,如果我碰巧知道本机指针的大小是<= 32位,或者long如果我碰巧知道本机指针的大小是<= 64位的话.但有没有更好或更清洁的方法来做到这一点?

编辑:从JNI函数返回一个指针原生到底是什么我也不想做.我宁愿返回一个代表本机资源的Java对象.但是,我返回的Java对象必须有一个包含指针的字段,这使我回到原始问题.

或者,是否有一些更好的方法让JNI函数返回对本机资源的引用?

Tom*_*ine 22

IIRC,无论是java.util.zipjava.nio只使用long.


Ale*_*rth 5

java.nio.DirectByteBuffer 做你想做的。

在内部,它使用 aprivate long address来存储指针值。呸!

使用 JNI 函数env->NewDirectByteBuffer((void*) data, sizeof(MyNativeStruct))在 C/C++ 端创建一个 DirectByteBuffer 并将其作为 ByteBuffer 返回给 Java 端。注意:在本机端释放这些数据是你的工作!它错过了标准 DirectBuffer 上可用的自动清洁器。

在 Java 端,您可以通过以下方式创建 DirectByteBuffer:

ByteBuffer directBuff = ByteBuffer.allocateDirect(sizeInBytes);
Run Code Online (Sandbox Code Playgroud)

将其视为某种 C malloc(sizeInBytes)注意:它具有自动清理器,可释放先前请求的内存。

但是使用 DirectByteBuffer 有几点需要考虑:

  • 如果您错过了直接的 ByteBuffer 引用,它可能是垃圾收集 (GC)。
  • 您可以读取/写入指向结构的值,但要注意偏移量和数据大小。编译器可能会为填充添加额外的空间并破坏结构中假定的内部偏移量。带指针的结构(步幅是 4 字节还是 8 字节?)也会让您的数据感到困惑。
  • Direct ByteBuffers 很容易作为本地方法的参数传递,也很容易作为返回值返回。
  • 您必须在 JNI 端强制转换为正确的指针类型。返回的默认类型env->GetDirectBufferAddress(buffer)void*
  • 一旦创建,您将无法更改指针值。
  • 您的工作是释放先前分配给本机端缓冲区的内存。你用过的那些env->NewDirectByteBuffer()