【问题标题】:What is the 'correct' way to store a native pointer inside a Java object?在 Java 对象中存储本机指针的“正确”方法是什么?
【发布时间】:2008-12-03 14:24:07
【问题描述】:

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

如果我碰巧知道本机指针的大小 int,或者如果我碰巧知道本机指针 long在尺寸方面。但是有没有更好或更清洁的方法来做到这一点?

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

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

【问题讨论】:

标签: java java-native-interface


【解决方案1】:

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

【讨论】:

  • 使用包装 long 的对象会产生开销:它可能会使内存消耗翻倍,因为对象外壳可能占用至少 8 个字节,更不用说包装类型的实例必须被垃圾回收跨度>
【解决方案2】:

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

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

使用 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】:

    没有什么好办法。在 SWT 中,使用了以下代码:

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

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

    【讨论】:

      【解决方案4】:

      更好的方法可能是将它存储在字节数组中,因为本机指针一开始就不是非常Java-ish。 ints 和 longs 更好地保留用于存储数值。

      【讨论】:

        【解决方案5】:

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

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

        至于您的问题,没有想到一种更简洁的方法来存储指针 - 如果您知道自己拥有什么,那么根据需要使用 int 或 long 或 byte[]。

        【讨论】:

        • 您能否举一个“对资源的逻辑引用”的示例?我编辑了我的问题以澄清我的意思。
        • 逻辑引用只是 jni 代码返回的一个数字,用于后续调用 jni 以引用某些内容。然后 jni 代码可以通过某种结构取消引用它,例如一个数组[ref][指针]。 hth
        • 这意味着维护一个数组,其中包含指向需要从 Java 引用的每个资源的指针。我认为这不是一个好主意...
        • 这就是 JVM 所做的事情。我看到了一些优点,Java 代码不需要处理 JNI 代码中指针的细节并且受到保护。您将多少资源共享回 Java 代码? 10000 个元素的数组似乎不会太大:)
        • 在实践中,可能几乎没有。但我只是不喜欢在对象创建上施加一些任意上限或必须编写代码来调整数组大小等等的想法,尤其是因为这是潜在错误的另一个来源。
        【解决方案6】:

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

        【讨论】:

          猜你喜欢
          • 2010-09-06
          • 1970-01-01
          • 2015-05-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-18
          • 1970-01-01
          • 2021-05-01
          相关资源
          最近更新 更多