It's a bit unclear what you're asking, so let me try to clarify a few points.
Any jobject
type you get in JNI, whether returned from a JNI call like FindClass
or passed in as an argument (jobject
, jclass
, jbyteArray
, etc), is a local reference. It has a very short lifespan. If you pass it to NewGlobalRef
, you get a global reference in return; this will last until you delete it.
Any JNI function that takes or returns a pointer type is giving you a pointer that's good until something invalidates it. For example, if you call GetStringUTFChars
, you get a const char*
that's valid until you call ReleaseStringUTFChars
.
References are not pointers, and pointers are not references. You can't pass a char*
to NewGlobalRef
, and you can't dereference a global reference (where "can't" is usually an error or a native crash).
What I assume you're doing is calling GetDirectByteBufferAddress
on a ByteBuffer
object, which returns a void*
that points to the start of the direct byte buffer. This pointer is valid until the storage is freed. How that happens depends upon how you allocated it:
- If you allocated the direct byte buffer with
ByteBuffer.allocateDirect()
, then Dalvik owns the storage. It will be freed when the ByteBuffer
becomes unreachable and is garbage collected.
- If you allocated the storage yourself, and associated it with a
ByteBuffer
with the JNI NewDirectByteBuffer
call, then it's valid until you free it.
For the allocateDirect()
case, it's very important that your native code stops using the pointer before your managed code discards the ByteBuffer
. One way to do this would be to retain a global reference to the ByteBuffer
in your native code, and invalidate your buffer pointer at the same time you delete the global reference. Depending on how your code is structured that may not be necessary.
See also the JNI Tips page.