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

2022-09-01 15:51:51

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

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

编辑:从JNI函数返回本机指针正是我不想做的。我宁愿返回一个表示本机资源的 Java 对象。但是,我返回的 Java 对象必须具有一个包含指针的字段,这会将我带回原始问题。

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


答案 1

IIRC,两者兼而有之,只使用.java.util.zipjava.niolong


答案 2

java.nio.DirectByteBuffer做你想做的事。

在内部,它使用 a 来存储指针值。哒!private long address

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

在Java端,你可以这样创建一个DirectByteBuffer:

ByteBuffer directBuff = ByteBuffer.allocateDirect(sizeInBytes);

把它想象成一种C的.注意:它具有自动清理程序,可以解除分配先前请求的内存。malloc(sizeInBytes)

但是关于使用DirectByteBuffer,需要考虑一些要点:

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

推荐