Есть ли способ передать массив Java на C через JNI, не делая его копии?

Я понимаю, что при использовании GetDoubleArrayElements именно JVM решает, копировать ли элементы массива. В этом случае есть ли способ избежать копирования? Если нет, есть ли другой способ перейти с Java на C без копирования? Я передаю очень большие массивы, и мне хотелось бы избежать копирования. Спасибо


person Elder    schedule 08.03.2011    source источник
comment
Вы можете использовать DoubleBuffer, чтобы обернуть прямой байтовый буфер. Это обновляет область памяти, которую можно напрямую использовать в Java / C.   -  person Peter Lawrey    schedule 08.03.2011


Ответы (1)


В руководстве JNI говорится:

В JDK / JRE 1.1 программисты могут использовать функции Get / ReleaseArrayElements для получения указателя на примитивные элементы массива. Если виртуальная машина поддерживает закрепление, возвращается указатель на исходные данные; в противном случае делается копия.

Новые функции, представленные в JDK / JRE 1.3, позволяют машинному коду получать прямой указатель на элементы массива, даже если виртуальная машина не поддерживает закрепление.

Этими «новыми функциями» являются GetPrimitiveArrayCritical и ReleasePrimitiveArrayCritical, которые полностью отключают сборку мусора и поэтому должны использоваться с осторожностью. Таким образом, это проблема виртуальной машины, а не API. Не забывайте, что без закрепления сборщик мусора может решить сжать кучу и физически переместить ваш массив, поэтому прямой указатель в конце концов будет бесполезен.

Как сказал Питер, вы можете работать с java.nio.DoubleBuffer вместо использования массивов. Функция JNI

void* GetDirectBufferAddress(JNIEnv* env, jobject buf);

позволяет получить к нему доступ.

person Tilo    schedule 11.03.2011
comment
Интересно, что предпочтительнее: byte [] с GetPrimitiveArrayCritical или ByteBuffer с GetDirectBufferAddress? - person Trilarion; 24.01.2018
comment
Это действительно зависит от вашего варианта использования. Одно из соображений может заключаться в использовании GetPrimitiveArrayCritical или GetArrayElements, когда ваши данные являются выходными данными вашего кода Java и входными данными вашего кода C. Вы бы использовали GetDirectBufferAddress, когда ваши данные текут в обратном направлении. - person Tilo; 24.01.2018