2013-11-09 7 views
1

Я пытаюсь расшифровать Speex кодированные аудиофайлы с использованием библиотеки Speex, но я всегда получаю ArrayIndexOutOfBoundsExceptionGetByteArrayRegion вызывает ArrayIndexOutOfBoundsException

JNIEXPORT jint JNICALL Java_com_app_shared_Speex_decode 
    (JNIEnv *env, jobject obj, jbyteArray encoded, jshortArray lin, jint size) { 

     jbyte buffer[dec_frame_size ]; 
     jshort output_buffer[dec_frame_size ]; 
     jsize encoded_length = size; 

     if (!codec_open) 
      return 0; 

     env->GetByteArrayRegion(encoded, rtp_header, encoded_length, buffer); 

     /* 
     jboolean isCopy; 
     jbyte* data = env->GetByteArrayElements(encoded, &isCopy); 
     if(isCopy){ 
     memcpy(buffer, data, encoded_length);    
     env->ReleaseByteArrayElements(encoded, data, JNI_ABORT); 
     } 
     */ 

     speex_bits_read_from(&dbits, (char *)buffer, encoded_length); 
     speex_decode_int(dec_state, &dbits, output_buffer); 

     std::string bufStr; 

     for(int i=0; i<20; i++){ 
      char buff[100]; 
      sprintf(buff, "Speex test %d => %d", i, output_buffer[i]); 
      bufStr = buff; 
      LOGI(bufStr.c_str()); 
     } 

     bufStr = "before SetShortArrayRegion"; 
     LOGI(bufStr.c_str()); 

     (env)->SetShortArrayRegion(lin, rtp_header, dec_frame_size, output_buffer); 

     bufStr = "after SetShortArrayRegion"; 
     LOGI(bufStr.c_str()); 

     return (jint)dec_frame_size;    
} 

я получаю:

SharedSpeex before SetShortArrayRegion 
dalvikvm JNI WARNING: JNI method called with exception pending 
dalvikvm    in Lcom/company/shared/Speex;.decode:([B[SI)I (SetShortArrayRegion) 
dalvikvm Pending exception is: 
dalvikvm java.lang.ArrayIndexOutOfBoundsException: [B offset=12 length=1634 src.length=1634 

Интересно то, что если я полностью комментарий строка, содержащая SetShortArrayRegion, исключение возникает при выходе из области:

SharedSpeex  before SetShortArrayRegion 
SharedSpeex  after SetShortArrayRegion 
AndroidRuntime Shutting down VM 
dalvikvm   threadid=1: thread exiting with uncaught exception (group=0xa62ca288) 
AndroidRuntime FATAL EXCEPTION: main 
AndroidRuntime java.lang.ArrayIndexOutOfBoundsException: [B offset=12 length=1634 src.length=1634 

Это в то время как в официальном JNI ясно справки о предпочитает GetByteArrayRegion вместо GetByteArrayElements из:

  • уменьшает риск ошибки программиста - не риск забыть вызвать Release после что-то не получается.
+0

сделал U получить декодирование speex, PLS помочь мне –

ответ

5

GetByteArrayRegion проверяет границы массива, чтобы убедиться, что вы не работаете над концом. GetByteArrayElements просто получает указатель на начало массива, поэтому ваш memcpy() может свободно пропустить незадолго до конца.

Причиной перебега отмечено в за исключением:

[B offset=12 length=1634 src.length=1634 

[B означает byte[]. Длина массива соответствует длине запроса (1634), но начинается с смещения 12 байтов в массив. Таким образом, вы пытаетесь прочитать 12 байтов за конец.

Исключения, выброшенные из кода Java, не прерывают ваш код C; VM просто устанавливает флаг в текущем потоке. Вы должны проверить их явно с помощью ExceptionCheck и либо очистить их, либо вернуться к Java-коду, где виртуальная машина продолжит процесс броска. Если у вас включен CheckJNI, и виртуальная машина видит, что вы делаете какую-либо из нескольких вызовов с поднятым исключением, вы получите «JNI WARNING» и VM abort.

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