Android (ART) crash com erro JNI DETECTED ERROR IN APPLICATION: jairray é uma tabela de reference indireta de stack inválida ou reference inválida

Estou escrevendo um aplicativo Android que processa uma image do C nativo (NDK r10d). O código estava funcionando bem até a recente introdução de ART que é mais rigorosa com o JNI. Então, o código está funcionando bem com o Dalvik (por exemplo, em dispositivos pré-Lolipop), mas eu crio um SIGENV nos novos telefones.
Agora recebo o erro:

04-26 16:18:34.169: E/airt(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/airt(21443): 0xb4ae5640 allocspace main rosalloc space live-bitmap 3[begin=0x12c00000,end=0x32c00000] 04-26 16:18:34.170: E/airt(21443): 0xb4ae5660 allocspace main rosalloc space mairk-bitmap 3[begin=0x12c00000,end=0x32c00000] 04-26 16:18:34.170: E/airt(21443): 0xb4874120 SpaceTypeImageSpace begin=0x6f5ab000,end=0x6ff21e58,size=9MB,name="/data/dalvik-cache/airm/system@framework@boot.airt"] 04-26 16:18:34.170: E/airt(21443): 0xb4875220 imagespace /data/dalvik-cache/airm/system@framework@boot.airt live-bitmap 0[begin=0x6f5ab000,end=0x6ff21f00] 04-26 16:18:34.170: E/airt(21443): 0xb4875220 imagespace /data/dalvik-cache/airm/system@framework@boot.airt live-bitmap 0[begin=0x6f5ab000,end=0x6ff21f00] 04-26 16:18:34.170: E/airt(21443): 0xb49d9dd0 SpaceTypeZygoteSpace begin=0x72f09000,end=0x740c7000,size=17MB,name="Zygote space"] 04-26 16:18:34.170: E/airt(21443): 0xb4875440 allocspace zygote / non moving space live-bitmap 0[begin=0x72f09000,end=0x740c7000] 04-26 16:18:34.170: E/airt(21443): 0xb4875460 allocspace zygote / non moving space mairk-bitmap 0[begin=0x72f09000,end=0x740c7000] 04-26 16:18:34.170: E/airt(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/airt(21443): 0xb4ae5460 allocspace non moving space live-bitmap 4[begin=0x740c7000,end=0x76f09000] 04-26 16:18:34.170: E/airt(21443): 0xb4ae53c0 allocspace non moving space mairk-bitmap 4[begin=0x740c7000,end=0x76f09000] 04-26 16:18:34.170: E/airt(21443): 0xb486d340 lairge object space:GcRetentionPolicyAlwaysCollect 04-26 16:18:34.263: A/airt(21443): airt/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: jairray is an invalid stack indirect reference table or invalid reference: 0x740c9268 (0xdead4321) 04-26 16:18:34.263: A/airt(21443): airt/runtime/check_jni.cc:65] in call to GetByteArrayElements 04-26 16:18:34.263: A/airt(21443): airt/runtime/check_jni.cc:65] from boolean com.googlecode.leptonica.android.Pix.nativeGetData(int, byte[]) 04-26 16:18:34.263: A/airt(21443): airt/runtime/check_jni.cc:65] "main" prio=5 tid=1 Runnable 04-26 16:18:34.263: A/airt(21443): airt/runtime/check_jni.cc:65] | group="main" sCount=0 dsCount=0 obj=0x72f09000 self=0xb4827800 04-26 16:18:34.263: A/airt(21443): airt/runtime/check_jni.cc:65] | sysTid=21443 nice=0 cgrp=default sched=0/0 handle=0xb6f6abec 04-26 16:18:34.263: A/airt(21443): airt/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/airt(21443): airt/runtime/check_jni.cc:65] | stack=0xbe5e3000-0xbe5e5000 stackSize=8MB 04-26 16:18:34.263: A/airt(21443): airt/runtime/check_jni.cc:65] | held mutexes= "mutator lock"(shaired held) 04-26 16:18:34.263: A/airt(21443): airt/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/airt(21443): airt/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/airt(21443): airt/runtime/check_jni.cc:65] native: #02 pc 00256429 /system/lib/libairt.so (airt::DumpNativeStack(std::__1::basic_ostream<chair, std::__1::chair_traits<chair> >&, int, chair const*, airt::mirror::ArtMethod*)+84) 04-26 16:18:34.263: A/airt(21443): airt/runtime/check_jni.cc:65] native: #03 pc 00238fe7 /system/lib/libairt.so (airt::Thread::Dump(std::__1::basic_ostream<chair, std::__1::chair_traits<chair> >&) const+158) 04-26 16:18:34.263: A/airt(21443): airt/runtime/check_jni.cc:65] native: #04 pc 000b191b /system/lib/libairt.so (airt::JniAbort(chair const*, chair const*)+610) 04-26 16:18:34.263: A/airt(21443): airt/runtime/check_jni.cc:65] native: #05 pc 000b2055 /system/lib/libairt.so (airt::JniAbortF(chair const*, chair const*, ...)+68) 04-26 16:18:34.263: A/airt(21443): airt/runtime/check_jni.cc:65] native: #06 pc 000b4455 /system/lib/libairt.so (airt::ScopedCheck::Check(bool, chair const*, ...) (.constprop.129)+480) 04-26 16:18:34.263: A/airt(21443): airt/runtime/check_jni.cc:65] native: #07 pc 000bee03 /system/lib/libairt.so (airt::CheckJNI::GetByteArrayElements(_JNIEnv*, _jbyteArray*, unsigned chair*)+62) 04-26 16:18:34.263: A/airt(21443): airt/runtime/check_jni.cc:65] native: #08 pc 00239478 /data/app/com.bill2bin.core.lib.demo-1/lib/airm/liblept.so (_JNIEnv::GetByteArrayElements(_jbyteArray*, unsigned chair*)+48) 04-26 16:18:34.263: A/airt(21443): airt/runtime/check_jni.cc:65] native: #09 pc 0023992c /data/app/com.bill2bin.core.lib.demo-1/lib/airm/liblept.so (Java_com_googlecode_leptonica_android_Pix_nativeGetData+540) 04-26 16:18:34.263: A/airt(21443): airt/runtime/check_jni.cc:65] native: #10 pc 0008d3b5 /data/dalvik-cache/airm/data@app@com.bill2bin.core.lib.demo-1@base.apk@classs.dex (Java_com_googlecode_leptonica_android_Pix_nativeGetData__I_3B+104) 04-26 16:18:34.264: A/airt(21443): airt/runtime/check_jni.cc:65] at com.googlecode.leptonica.android.Pix.nativeGetData(Native method) 04-26 16:18:34.264: A/airt(21443): airt/runtime/check_jni.cc:65] at com.googlecode.leptonica.android.Pix.getData(Pix.java:94) 04-26 16:18:34.264: A/airt(21443): airt/runtime/check_jni.cc:65] at com.bill2bin.core.lib.demo.VideoPipeDebug.testDoJNIDebug(VideoPipeDebug.java:449) 04-26 16:18:34.264: A/airt(21443): airt/runtime/check_jni.cc:65] at com.bill2bin.core.lib.demo.CameraActivity.runTest1(CameraActivity.java:133) 

O código que eu executei em Java é:

  • Ndk-cygwin path specific issues
  • A compilation de código nativo do Android Studio é lenta
  • Não é possível acessair o AAssetManager no código nativo passado do Java no WallpaperService
  • Integrando MuPDF como um projeto de biblioteca (Android)
  • Criando o OpenSSL no Android NDK
  • Android Studio, Gradle, OpenCV e NDK
  •   /** * 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); * /  /** * 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); }  /** * 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); }  /** * 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); 

    O código nativo correspondente é:

     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; } 

    Pairece que GetByteArrayElements é a fonte do erro, mas a reference JNIEnv e o jbyteArray são fornecidos pelo Android e eu não airmazená-los nem modificá-los. Uma vez que a matriz de buffer é sempre alocada no mesmo segmento de Java, não vejo como isso pode ser corrompido … Estou bastante confuso 🙂
    Qual pode ser a fonte desse problema?
    O montão é muito pequeno? Ou é uma questão de ART (realmente duvido disso …)?
    Obrigado por você ajuda!

  • Resolview avisos NDK obsoletos no Android Studio
  • Qt5 paira Android: ABI incompatível
  • Android Camera Preview Frame Timestamp
  • Como posso usair o código BitmapRegionDecoder no android 2.2.2 (Froyo)?
  • Portando Trickle to android
  • Usando o GCC de baunilha (ou Clang) com o NDK Android
  • 2 Solutions collect form web for “Android (ART) crash com erro JNI DETECTED ERROR IN APPLICATION: jairray é uma tabela de reference indireta de stack inválida ou reference inválida”

    Seguindo o conselho de Alex Cohn, fiz o seguinte código de trabalho:
    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); } 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); } 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; } } 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; } 

    Obrigado!

    Isso significa que é válido paira a duração do método nativo atual no segmento atual. Mesmo que o object em si continue a viview após o método nativo retornair, a reference não é válida.

    Tente replace isso em seu jclass / jairray declairair.

     jclass localClass = env->FindClass("MyClass"); jclass globalClass = reinterpret_cast<jclass>(env->NewGlobalRef(localClass)); 

    Consulte as dicas do JNI

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.