Вот возможное решение, учитывая небольшую информацию, которую вы предоставили.
На стороне Java у вас будет:
package com.stackoverflow;
public class JNIQuestion
{
static native void fillByteArray(byte[] buffer);
}
А на стороне C у вас будет:
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);
}
Использование прямого ByteBuffer
(ByteBuffer.allocateDirect()
) также является возможным решением. Однако я использую прямой ByteBuffer
, только когда мне нужно заполнить данные со стороны Java очень точными смещениями в буфере.
Что касается производительности, решение, использующее byte[]
, должно быть удовлетворительным, поскольку JVM, скорее всего, закрепит байтовый массив вместо его копирования при вызове GetByteArrayElements()
.
Вообще говоря, вам нужно минимизировать количество вызовов JNI, что подразумевает, что доступ к полям объекта со стороны C или выделение Java со стороны C будут влиять на производительность.
В любом случае, сначала профиль, затем оптимизировать.
PS: я не пытался скомпилировать код, могут быть опечатки. См. Руководство по JNI и Учебное пособие по JNI .