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

时间:2008-12-03 14:24:07

标签: java java-native-interface

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

我可以将指针视为Java int,如果我碰巧知道本机指针的大小是< = 32位,或者如果我碰巧知道本地指针那么Java long是< = 64位的大小。但有更好或更清洁的方法吗?

编辑:从JNI函数返回本机指针正是我想要做的事情。我宁愿返回一个代表本机资源的Java对象。但是,我返回的Java对象必须有一个包含指针的字段,这会让我回到最初的问题。

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

6 个答案:

答案 0 :(得分:22)

IIRC,java.util.zipjava.nio只使用long

答案 1 :(得分:3)

没有好办法。在SWT中,使用此代码:

int /*long*/ hModule = OS.GetLibraryHandle ();

并且有一个工具可以通过移动注释来转换32位和64位之间的代码。丑陋但有效。如果Sun添加了一个“NativePointer”对象或类似的东西,但事情本来会容易得多。

答案 2 :(得分:3)

java.nio.DirectByteBuffer做你想要的。

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

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

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

ByteBuffer directBuff = ByteBuffer.allocateDirect(sizeInBytes);

将其视为C的malloc(sizeInBytes)注意:它具有自动清除功能,可以释放先前请求的内存。

但是有一些要考虑使用DirectByteBuffer的要点:

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

答案 3 :(得分:2)

更好的方法是将它存储在字节数组中,因为本机指针首先不是非常Java。 intlong最好保留用于存储数值。

答案 4 :(得分:2)

我认为这是从一些JNI代码返回的指针,我的建议是就是不要这样做 :)

理想情况下,JNI代码应该传递给资源的某种逻辑引用,而不是实际的指针?

关于你的问题,没有什么可以想到存储指针的更简洁的方法 - 如果你知道你有什么,那么根据需要使用int或long或byte []。

答案 5 :(得分:0)

你可以看看C#使用IntPtr类型处理它的方式。通过创建自己的类型来保存指针,相同的类型可以用作32位或64位,具体取决于您所使用的系统。