Here is a possible solution considering the small of information you gave.
On the Java side of things, you would have:
package com.stackoverflow;
public class JNIQuestion
{
static native void fillByteArray(byte[] buffer);
}
And on the C side you would have:
JNIEXPORT void JNICALL Java_com_stackoverflow_JNIQuestion_fillByteArray(JNIEnv* env, jbyteArray array)
{
jboolean isCopy;
jbyte* buffer = (*env)->GetByteArrayElements(env, array, &isCopy);
jsize length = (*env)->GetArrayLength(env, array);
jsize i;
// do something with the buffer here, replace with something meaningful
// PAY ATTENTION TO BUFFER OVERFLOW, DO NOT WRITE BEYOND BUFFER LENGTH
for (i = 0; i < length; ++i)
buffer[i] = i;
// here it is important to use 0 so that JNI takes care of copying
// the data back to the Java side in case GetByteArrayElements returned a copy
(*env)->ReleaseByteArrayElements(env, buffer, 0);
}
Using a direct ByteBuffer
(ByteBuffer.allocateDirect()
) is also a possible solution. However I only use a direct ByteBuffer
when I need to fill data from the Java side a very precise offsets in the buffer.
About performance, the solution using a byte[]
should be satisfactory as the JVM is likely to pin the byte array instead of copying it when invoking GetByteArrayElements()
.
Generally speaking, you will want to minimize the number of JNI calls which implies that accessing object fields from the C side or allocating Java from the C side will have an impact on performance.
In any case, profile first, optimize next.
PS: I didn't try to compile the code, there might be typos. Refer to the JNI Guide and the JNI Tutorial.