Android (ART) bloqueo con error JNI DETECTED ERROR EN APLICACIÓN: jarray es una tabla de referencia indirecta de pila no válida o una referencia no válida
Estoy escribiendo una aplicación de Android que procesa una imagen de la nativa C (NDK r10d). El código estaba funcionando bien hasta la introducción reciente de ART que es más estricta con JNI. Así que el código está funcionando bien con Dalvik (por ejemplo, en dispositivos pre-Lolipop), pero ii crea un SIGENV en los teléfonos más nuevos.
Ahora obtengo el error:
04-26 16:18:34.169: E/art(21443): 0xb4a2dd00 SpaceTypeMallocSpace begin=0x12c00000,end=0x12e01000,limit=0x32c00000,size=2MB,capacity=192MB,non_growth_limit_capacity=512MB,name="main rosalloc space"] 04-26 16:18:34.170: E/art(21443): 0xb4ae5640 allocspace main rosalloc space live-bitmap 3[begin=0x12c00000,end=0x32c00000] 04-26 16:18:34.170: E/art(21443): 0xb4ae5660 allocspace main rosalloc space mark-bitmap 3[begin=0x12c00000,end=0x32c00000] 04-26 16:18:34.170: E/art(21443): 0xb4874120 SpaceTypeImageSpace begin=0x6f5ab000,end=0x6ff21e58,size=9MB,name="/data/dalvik-cache/arm/system@[email protected]"] 04-26 16:18:34.170: E/art(21443): 0xb4875220 imagespace /data/dalvik-cache/arm/system@[email protected] live-bitmap 0[begin=0x6f5ab000,end=0x6ff21f00] 04-26 16:18:34.170: E/art(21443): 0xb4875220 imagespace /data/dalvik-cache/arm/system@[email protected] live-bitmap 0[begin=0x6f5ab000,end=0x6ff21f00] 04-26 16:18:34.170: E/art(21443): 0xb49d9dd0 SpaceTypeZygoteSpace begin=0x72f09000,end=0x740c7000,size=17MB,name="Zygote space"] 04-26 16:18:34.170: E/art(21443): 0xb4875440 allocspace zygote / non moving space live-bitmap 0[begin=0x72f09000,end=0x740c7000] 04-26 16:18:34.170: E/art(21443): 0xb4875460 allocspace zygote / non moving space mark-bitmap 0[begin=0x72f09000,end=0x740c7000] 04-26 16:18:34.170: E/art(21443): 0xb4a2dc80 SpaceTypeMallocSpace begin=0x740c7000,end=0x740d6000,limit=0x76f09000,size=60KB,capacity=46MB,non_growth_limit_capacity=46MB,name="non moving space"] 04-26 16:18:34.170: E/art(21443): 0xb4ae5460 allocspace non moving space live-bitmap 4[begin=0x740c7000,end=0x76f09000] 04-26 16:18:34.170: E/art(21443): 0xb4ae53c0 allocspace non moving space mark-bitmap 4[begin=0x740c7000,end=0x76f09000] 04-26 16:18:34.170: E/art(21443): 0xb486d340 large object space:GcRetentionPolicyAlwaysCollect 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: jarray is an invalid stack indirect reference table or invalid reference: 0x740c9268 (0xdead4321) 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] in call to GetByteArrayElements 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] from boolean com.googlecode.leptonica.android.Pix.nativeGetData(int, byte[]) 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] "main" prio=5 tid=1 Runnable 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] | group="main" sCount=0 dsCount=0 obj=0x72f09000 self=0xb4827800 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] | sysTid=21443 nice=0 cgrp=default sched=0/0 handle=0xb6f6abec 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] | state=R schedstat=( 427402282 63106827 397 ) utm=28 stm=14 core=3 HZ=100 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] | stack=0xbe5e3000-0xbe5e5000 stackSize=8MB 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] | held mutexes= "mutator lock"(shared held) 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #00 pc 00004e64 /system/lib/libbacktrace_libc++.so (UnwindCurrent::Unwind(unsigned int, ucontext*)+23) 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #01 pc 00003665 /system/lib/libbacktrace_libc++.so (Backtrace::Unwind(unsigned int, ucontext*)+8) 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #02 pc 00256429 /system/lib/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, int, char const*, art::mirror::ArtMethod*)+84) 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #03 pc 00238fe7 /system/lib/libart.so (art::Thread::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const+158) 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #04 pc 000b191b /system/lib/libart.so (art::JniAbort(char const*, char const*)+610) 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #05 pc 000b2055 /system/lib/libart.so (art::JniAbortF(char const*, char const*, ...)+68) 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #06 pc 000b4455 /system/lib/libart.so (art::ScopedCheck::Check(bool, char const*, ...) (.constprop.129)+480) 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #07 pc 000bee03 /system/lib/libart.so (art::CheckJNI::GetByteArrayElements(_JNIEnv*, _jbyteArray*, unsigned char*)+62) 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #08 pc 00239478 /data/app/com.bill2bin.core.lib.demo-1/lib/arm/liblept.so (_JNIEnv::GetByteArrayElements(_jbyteArray*, unsigned char*)+48) 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #09 pc 0023992c /data/app/com.bill2bin.core.lib.demo-1/lib/arm/liblept.so (Java_com_googlecode_leptonica_android_Pix_nativeGetData+540) 04-26 16:18:34.263: A/art(21443): art/runtime/check_jni.cc:65] native: #10 pc 0008d3b5 /data/dalvik-cache/arm/data@[email protected]@[email protected] (Java_com_googlecode_leptonica_android_Pix_nativeGetData__I_3B+104) 04-26 16:18:34.264: A/art(21443): art/runtime/check_jni.cc:65] at com.googlecode.leptonica.android.Pix.nativeGetData(Native method) 04-26 16:18:34.264: A/art(21443): art/runtime/check_jni.cc:65] at com.googlecode.leptonica.android.Pix.getData(Pix.java:94) 04-26 16:18:34.264: A/art(21443): art/runtime/check_jni.cc:65] at com.bill2bin.core.lib.demo.VideoPipeDebug.testDoJNIDebug(VideoPipeDebug.java:449) 04-26 16:18:34.264: A/art(21443): art/runtime/check_jni.cc:65] at com.bill2bin.core.lib.demo.CameraActivity.runTest1(CameraActivity.java:133)
El código que ejecuto en Java es:
- Java: escala Mapsforge Map al usar mosaicos de mapa de bits en línea en lugar del renderizador sin conexión
- Obteniendo clase por su nombre
- Android: IllegalStateException - ¿Cuándo es lanzado?
- ¿Pueden los recursos de ID de Android referirse hacia adelante?
- ¿Cuál es la diferencia entre `opencv.android.JavaCameraView` y` opencv.android.NativeCameraView`
/** * Return the raw bytes of the native PIX object. You can reconstruct the * Pix from this data using createFromPix(). * * @return a copy of this PIX object's raw data */ public byte[] getData() { int size = nativeGetDataSize(mNativePix); // Size is usually quite big since I work on pictures (1Mo-300Ko) byte[] buffer = new byte[size]; if (!nativeGetData(mNativePix, buffer)) { throw new RuntimeException("native getData failed"); } return buffer; } private static native boolean nativeGetData(long nativePix, byte[] data);
El código nativo correspondiente es:
jboolean Java_com_googlecode_leptonica_android_Pix_nativeGetData(JNIEnv *env, jclass clazz, jlong nativePix, jbyteArray data) { PIX *pix = (PIX *) nativePix; jbyte *data_buffer = env->GetByteArrayElements(data, NULL); l_uint8 *byte_buffer = (l_uint8 *) data_buffer; size_t size = 4 * pixGetWpl(pix) * pixGetHeight(pix); memcpy(byte_buffer, pixGetData(pix), size); env->ReleaseByteArrayElements(data, data_buffer, 0); return JNI_TRUE; }
Parece que GetByteArrayElements es el origen del error, pero la referencia JNIEnv y el jbyteArray son proporcionados por Android y no los almaceno ni los modifico. Dado que la matriz de búfer siempre se asigna en el mismo hilo de Java, no veo cómo se puede corromper … Estoy muy desconcertado 🙂
¿Cuál puede ser la fuente de este problema?
¿El montón es demasiado pequeño? ¿O es un tema de ART (realmente lo dudo …)?
Gracias por tu ayuda !
- ¿Es necesario un profundo conocimiento de Java para Android?
- Escuche el cierre de sesión de Facebook con el botón de inicio de sesión. (4.1)
- Uso de Google para acceder a las hojas de cálculo de Google (u otras aplicaciones de Google) en Android
- Cómo POST datos en Android a servidor en formato JSON?
- Pruebas en modo "Avión" en Android Emulator
- Spinner Error al establecer setOnItemSelectedListener
- Java.io.IOException: No queda espacio en el dispositivo Android
- Asegúrese de que las fotos se guardan con la misma orientación que se tomaron?
Siguiendo el consejo de Alex Cohn hice el siguiente código de trabajo:
JAVA
public byte[] getData() { byte[] buffer = nativeGetData(mNativePix); if (buffer == null) { throw new RuntimeException("native getData failed"); } return buffer; } private static native byte[] nativeGetData(long nativePix);
Nativo
jbyteArray Java_com_googlecode_leptonica_android_Pix_nativeGetData( JNIEnv *env, jclass clazz, jlong nativePix) { PIX *pix = (PIX *) nativePix; // Get the size size_t size = 4 * pixGetWpl(pix) * pixGetHeight(pix); jbyteArray result = env->NewByteArray(size); if (result == NULL) { LOGE("Cannot allocate JNI Byte Array"); return NULL; /* out of memory error thrown */ } // move from the Pix to the java structure env->SetByteArrayRegion(result, 0, size,(jbyte*)pixGetData(pix)); return result; }
¡Gracias!
Esto significa que es válido para la duración del método nativo actual en el subproceso actual. Incluso si el objeto en sí continúa viviendo después de regresar el método nativo, la referencia no es válida.
Intente reemplazar esto en su declaración jclass / jarray.
jclass localClass = env->FindClass("MyClass"); jclass globalClass = reinterpret_cast<jclass>(env->NewGlobalRef(localClass));
Sugerencias para JNI
- Análisis de un ID de cadena con SugarORM y GSON
- Adaptador con hasStableIds utilizando GUID o Strings como Ids