2015-03-01 3 views
1

я создаю два массива в C++, которые будут считываться в стороне Java:делает NewDirectByteBuffer создать копию в машинный код

env->NewDirectByteBuffer 
env->NewByteArray 

делает эти функции копирования в буфер я отправить его? Нужно ли создавать буфер в куче на стороне C++ или нормально его создавать в стеке, потому что jvm его скопирует?

, например, будет этот код работать нормально:

std::string stam = "12345"; 
const char *buff = stam.c_str(); 
jobject directBuff = env->NewDirectByteBuffer((void*)buff, (jlong) stam.length()); 

Другой пример:

std::string md5 "12345";  
jbyteArray md5ByteArray = env->NewByteArray((jsize) (md5.length())); 
env->SetByteArrayRegion(md5ByteArray, 0, (jsize) (md5.length()), (jbyte*)  
md5.c_str()); 

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

ответ

1

Ваше использование DirectByteBuffer почти наверняка потерпит неудачу в зрелищных, демпинговых и непредсказуемых путях. И его поведение может различаться между реализациями JVM и операционными системами. Проблема в том, что ваша прямая память должна оставаться в силе в течение срока действия DirectByteBuffer. Так как ваша строка находится в стеке, она быстро выходит из сферы действия. Между тем код Java может или не может продолжать использовать DirectByteBuffer, в зависимости от того, что это такое. Вы тоже пишете код Java? Можете ли вы гарантировать, что его использование DirectByteBuffer будет завершено до того, как строка выйдет за рамки?

Даже если вы можете гарантировать, что, поймите, что Java GC не является детерминированным. Слишком легко думать, что ваш DirectByteBuffer больше не используется, но тем временем он блуждает по невосприимчивым объектам, которые в конечном итоге могут быть вызваны GC, что может вызвать некоторый метод finalize(), который случайно затрагивает DirectByteBuffer , и - kablooey! На практике очень сложно сделать эти гарантии, кроме блоков «разделяемой памяти», которые никогда не уходят на всю жизнь вашего приложения.

NewDirectByteBuffer также не так быстр (по крайней мере, не в Windows), несмотря на интуитивное предположение, что производительность - это то, о чем все. Я экспериментально обнаружил, что быстрее копировать 1000 байтов, чем создавать один DirectByteBuffer.Обычно намного быстрее, чтобы ваша Java передала байты [] в C++ и в нее были включены байты C++ (гм, если они подходят). В целом, я делаю эти рекомендации:

  1. Вызов NewByteArray() и SetByteArrayRegion() возвращает полученный jBytearray на Java и не имеют никаких забот.
  2. Если производительность является требование, передать байт [] с Java на C++ и имеют C++ заполнить его . Вы, возможно, потребуется два C++ вызывает, один, чтобы получить размер и следующий , чтобы получить данные.
  3. Если данные огромны, используйте NewDirectBtyeBuffer и , убедитесь, что данные C++ остаются «навсегда», или пока вы не достигнете , и убедитесь, что вы выбрали DirectByteBuffer.

Я также прочитал, что как C++, так и Java могут отображать один и тот же файл, и это очень хорошо работает для больших данных.

+0

Спасибо за хороший ответ. java side can not создает bytearray и отправляет его на сторону C++ для заполнения, потому что он не знает размер массива. Вот почему мне нужна сторона C++ для создания буфера – Shay

1
  • NewDirectByteBuffer: «Выделяет и возвращает прямой java.nio.ByteBuffer со ссылкой на сообщение блок памяти, начинающийся с адреса адреса памяти и байт пропускной способности.

    «Исходный код, который вызывает эту функцию и возвращает полученный объект байтового буфера на код уровня Java, должен гарантировать, что буфер относится к допустимой области памяти который доступен для чтения и, при необходимости, для написания. Попытка доступа недействительной ячейки памяти из кода будет возвращать либо произвольное значение, не имеет никакого видимого эффекта, или вызвать неопределенное исключение быть выброшено "

    Нет копирование там

  • New<Primitive>Array:... Только аргументы JNIEnv * и length, так что нет ничего, чтобы скопировать

  • Set<Primitive>Array:. «семейство функций, которая копирует обратно область примитивного массива из буфера.»

+0

Вы должны добавить, что разработчики должны делать 'GetDirectBufferAddress', чтобы получить« указатель »в буфер. – Brandon

+0

@Brandon Почему разработчик должен вызвать этот метод, когда он первым отправил буфер? – EJP

+0

Если я понимаю ваш ответ, NewDirectByteBuffer не делает копию буфера, поэтому на стороне C++ мне нужно убедиться, что буфер выделен в куче, а не в стеке, чтобы сторона java читала действительную память. Это верно? Пример, который я написал, неверен, и я могу сделать memcopy строки в буфере char *. setByteArray создает копию, поэтому в этом случае я могу использовать строку в стеке без выделения на кучу .. это правильно? – Shay

Смежные вопросы