Android (ART) crash with error JNI DETECTED ERROR IN APPLICATION: jarray is an invalid stack indirect reference table or invalid reference



I am writing an Android application that processes a picture from the native C (NDK r10d). The code was working well until recent ART introduction that is more strict with JNI. So the code is working fine with Dalvik (e.g. on pre-Lolipop devices) but ii creates a SIGENV on the newest phones.
I now get the 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@framework@boot.art"]
04-26 16:18:34.170: E/art(21443): 0xb4875220 imagespace /data/dalvik-cache/arm/system@framework@boot.art live-bitmap 0[begin=0x6f5ab000,end=0x6ff21f00]
04-26 16:18:34.170: E/art(21443): 0xb4875220 imagespace /data/dalvik-cache/arm/system@framework@boot.art 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@app@com.bill2bin.core.lib.demo-1@base.apk@classes.dex (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)

The code I run in Java is:

  • How to create a DialogFragment without title?
  • Android: What are the recommended configurations for Proguard?
  • Android /FBReaderJ/gen already exists but is not a source folder. Convert to a source folder or rename it
  • Disabling the fullscreen editing view for soft keyboard input in landscape?
  • How to determine if network type is 2G, 3G or 4G
  • Android Studio, Suddenly got GPU Driver Issue when running emulator
  •     /**
         * 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);
    

    The corresponding native code is:

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

    It seems that GetByteArrayElements is the source of the error, but the JNIEnv reference and the jbyteArray are provided by Android and I do not store nor modify them. Since the buffer array is always allocated in the same Java thread, I do not see how it can be corrupted…I am quite puzzled 🙂
    What can be the source of this issue?
    Is the heap too small? Or is it an ART issue (I really doubt it though…) ?
    Thanks for you help !

  • Unable to open debugger port : java.net.SocketException “Socket closed”
  • How to programmatically force bluetooth low energy service discovery on Android without using cache
  • Firebase Analytics custom events params
  • Android VideoView Proportional Scaling
  • Android Studio: Buildtools 24.0.1 requires Java 1.8 or above.
  • onLocationChanged not called on some devices
  • 2 Solutions collect form web for “Android (ART) crash with error JNI DETECTED ERROR IN APPLICATION: jarray is an invalid stack indirect reference table or invalid reference”

    Following Alex Cohn ‘s advice I made the following code work:
    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);
    

    Native

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

    Thanks!

    This means that it’s valid for the duration of the current native method in the current thread. Even if the object itself continues to live on after the native method returns, the reference is not valid.

    Try replace this in your jclass/jarray declare.

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

    Refer JNI Tips

    Android Babe is a Google Android Fan, All about Android Phones, Android Wear, Android Dev and Android Games Apps and so on.