What is the 'correct' way to store a native pointer inside a Java object?

后端 未结 6 1648
南方客
南方客 2020-11-30 06:38

What is the \'correct\' way to store a native pointer inside a Java object?

I could treat the pointer as a Java int, if I happen to know that native poi

相关标签:
6条回答
  • 2020-11-30 07:02

    java.nio.DirectByteBuffer does what you want.

    Internally it uses a private long address to store pointer value. Dah !

    Use JNI function env->NewDirectByteBuffer((void*) data, sizeof(MyNativeStruct)) to create a DirectByteBuffer on C/C++ side and return it to Java side as a ByteBuffer. Note: It's your job to free this data at native side! It miss the automatic Cleaner available on standard DirectBuffer.

    At Java side, you can create a DirectByteBuffer this way :

    ByteBuffer directBuff = ByteBuffer.allocateDirect(sizeInBytes);
    

    Think it as sort of C's malloc(sizeInBytes). Note: It has as automatic Cleaner, which deallocates the memory previously requested.

    But there are some points to consider about using DirectByteBuffer:

    • It can be Garbage Collected (GC) if you miss your direct ByteBuffer reference.
    • You can read/write values to pointed structure, but beware with both offset and data size. Compiler may add extra spaces for padding and break your assumed internal offsets in structure. Structure with pointers (stride is 4 or 8 bytes ?) also puzzle your data.
    • Direct ByteBuffers are very easy to pass as a parameter for native methods, as well to get it back as return.
    • You must cast to correct pointer type at JNI side. Default type returned by env->GetDirectBufferAddress(buffer) is void*.
    • You are unable to change pointer value once created.
    • Its your job to free memory previously allocated for buffers at native side. That ones you used with env->NewDirectByteBuffer().
    0 讨论(0)
  • 2020-11-30 07:04

    You could look to the way C# handles this with the IntPtr type. By creating your own type for holding pointers, the same type can be used as a 32-bit or 64-bit depending on the system you're on.

    0 讨论(0)
  • 2020-11-30 07:16

    IIRC, both java.util.zip and java.nio just use long.

    0 讨论(0)
  • 2020-11-30 07:16

    I assume that this is a pointer returned from some JNI code and my advice would be just dont do it :)

    Ideally the JNI code should pass you back some sort of logical reference to the resource and not an actual pointer ?

    As to your question there is nothing that comes to mind about a cleaner way to store the pointer - if you know what you have then use either the int or long or byte[] as required.

    0 讨论(0)
  • 2020-11-30 07:18

    A better way might by to store it in a byte array, since native pointers aren't very Java-ish in the first place. ints and longs are better reserved for storing numeric values.

    0 讨论(0)
  • 2020-11-30 07:19

    There is no good way. In SWT, this code is used:

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

    and there is a tool which converts the code between 32bit and 64bit by moving the comment. Ugly but it works. Things would have been much easier if Sun had added an object "NativePointer" or something like that but they didn't.

    0 讨论(0)
提交回复
热议问题