Есть ли способ установить память DirectByteBuffer с JNI? - PullRequest
0 голосов
/ 25 декабря 2018

По какой-то причине я должен использовать специфичный для Linux API, который в настоящее время недоступен непосредственно из JVM, и должен разработать метод, который принимает ByteBuffer ( Это определенно не из-за какой-то причины производительности ),Вот как это выглядит:

//I need to call device-specific ioctl here
//and fill the ByteBuffer
public static native long putIntoByteBuffer(int fd, ByteBuffer buf);

Сгенерированный заголовочный файл:

JNIEXPORT jlong JNICALL Java_net_abcomm_PlatformSpecific_putIntoByteBuffer
  (JNIEnv *, jclass, jint, jobject);

Как получить char* по заданному ByteBuffer с JNI?Я мог бы использовать DirectBuffer, но тогда я буду ограничен только DirectBuffer с, и, кроме того, генерируется следующее предупреждение:

warning: DirectBuffer is internal proprietary API and may be removed in a 
future release
import sun.nio.ch.DirectBuffer;

Также есть GetDirectBufferAddress возвращение void*, но ограничено DirectBuffer с.

1 Ответ

0 голосов
/ 25 декабря 2018

Предполагая, что вы ограничиваете себя общедоступными классами и их общедоступными API, у вас есть две относительно эффективные альтернативы для решения проблемы, но их объединяет то, что они полагаются на помещение данных в Java byte[].Это не так сложно:

/* error checks omitted for brevity; these are *not* optional */

char *cBytes = /* ... */;
size_t numCBytes = /* ... */;
jbyteArray javaBytes = /* ... */;

jsize numBytes = (*env)->GetArrayLength(env, javaBytes);
jbyte *bytes = (*env)->GetPrimitiveArrayCritical(env, javaBytes, NULL);
/* It is pretty safe to assume that jbyte is a character type, such as signed
   char, in any C implementation that supports the JNI at all */
/* Assumes numCBytes <= numBytes; adjust as necessary if that may not be true: */
memcpy(bytes, cBytes, numCBytes);
(*env)->ReleasePrimitiveArrayCritical(env, javaBytes, bytes, 0);

Обратите внимание, что если функция JNI выполняет какой-либо ввод-вывод для получения байтов, она может прочитать их непосредственно в bytes (в зависимости от собственных требованийне в JNI), но в этом случае вы должны использовать не Critical версии подпрограмм Get / Release.

С учетом сказанного, ваши две основные альтернативы для получения всех данныхпуть в ByteBuffer:

  • , если буфер hasArray(), затем получить byte[] для вышеуказанной процедуры с помощью метода буфера array().Готово и сделано.

  • , если буфер не hasArray(), или если вы не хотите проверять, тогда получите byte[], создав его заново и после загрузкис помощью описанной выше процедуры скопируйте содержимое в буфер с помощью метода Bulb put(byte[]) или put(byte[], int, int).Очевидно, что это включает дополнительную копию относительно другой альтернативы и использует дополнительный временный объект.

Я не могу рекомендовать использовать конкретный конкретный ByteBuffer подкласс или полагаться на непубличныйметоды.Возможно, стоит подумать, если бы производительность была высоким приоритетом, но вы, кажется, сказали, что это не так.

...