How to send Java ByteBuffer to C using JNI?

Viewed 5055

Firstly, I want to say that the old answers doesn't work (for example, GetDirectBufferAddress function in below answers want one parameter now) at the moment as here:

JNI - native method with ByteBuffer parameter

and here,

how to write and read from bytebuffer passing from java to jni

It would be better if someone helps..

So, I can't send correctly my ByteBuffer, which's some elements filled, to C from Java using JNI and I can't return that ByteBuffer's elements again to C

My native function decleration:

public native int myfunc(ByteBuffer pkt);

Allocation for it

private ByteBuffer pkt = ByteBuffer.allocate(1000);

I am calling it in this way:

System.out.println(myfunc(pkt));  // Doesn't works, throws exception
pkt.position(0);
System.out.println(pkt.get()); // works, when I do comment line above .println

And my C codes as below:

JNIEXPORT jint JNICALL Java_xxx_myfunc(JNIEnv *, jobject, jobject); // header


JNIEXPORT jint JNICALL Java_xxx_myfunc(JNIEnv *env, jobject obj, jobject pkt) // function
{
  jbyte *buff = (jbyte *) env->GetDirectBufferAddress(pkt);
  // buff[0] = 0; I've also tried in this way
  return buff[0];
  //return 1; if I return 1, it returns correctly
}

when I run the java program it throws exception. How can I return my filled ByteBuffer values from C?

EDIT

A fatal error has been detected by the Java Runtime Environment:
EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x719c16b8, pid=1096, tid=1900
2 Answers

To use GetDirectBufferAddress() you must guarantee that pkt is direct (you can check this with isDirect()). The easy way to obtain such object is ByteBuffer.allocateDirect(). Direct ByteBuffer can be created from C++, too.

The difference between direct and indirect ByteBuffer is clearly explained in the Java oficial doc.

Update I see your update. No, ByteBuffer.allocate(1000) does not produce a DirectByteBuffer.

As @Tom Blodget correctly noted, the JNI spec explicitly says that GetDirectBufferAddress() can return NULL. This works both ways: the call itself should not crash if pkt is an indirect ByteBuffer, but you must check the result even if you are sure that pkt is a DirectByteBuffer.

You can't use GetDirectBufferAddress() except on a direct byte buffer. You don't have a direct byte buffer.

Related