簡體   English   中英

Android(ART)崩潰,錯誤JNI DETECTED ERROR IN APPLICATION:jarray是無效的堆棧間接引用表或無效的引用

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


我正在編寫一個處理原生C(NDK r10d)圖片的Android應用程序。 該代碼運行良好,直到最近的ART介紹對JNI更嚴格。 因此代碼與Dalvik一起工作正常(例如在Lolipop之前的設備上),但ii在最新的手機上創建了一個SIGENV。
我現在得到錯誤:

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)

我在Java中運行的代碼是:

    /**
     * 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);

相應的本機代碼是:

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

似乎GetByteArrayElements是錯誤的來源,但JNIEnv引用和jbyteArray是由Android提供的,我不存儲也不修改它們。 由於緩沖區數組總是在同一個Java線程中分配,我不知道它是如何被破壞的...我很困惑:)
這個問題的根源是什么?
堆太小了嗎? 或者它是一個ART問題(我真的懷疑它雖然......)?
謝謝你的幫助!

按照Alex Cohn的建議,我做了以下代碼:
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);


本地人

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


謝謝!

這意味着它在當前線程中當前本機方法的持續時間內有效。 即使在本機方法返回后對象本身繼續存在,引用也無效。

嘗試在jclass / jarray聲明中替換它。

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

參考JNI提示

我遇到了同樣的問題。 我編寫了一個C函數,從Java中獲取jbyteArray,這與其他現有和正在運行的函數非常相似。 但它與關於訪問已刪除的很久以前的對象的可怕消息猛烈地崩潰,在50個記錄等的表中訪問記錄號~6000 ...我將我的代碼簡化為最小化並注意到在嘗試訪問jbyteArray期間函數失敗被傳遞給它。 無論我如何形成這個數組,無論從哪個線程調用。 我檢查了簽名和我能做的一切。 功能肯定被調用,因為我可以打印從它進行記錄。

在我讀完這個主題之后,我感到注定了:)我絕對無法在我的c函數中生成數據。

對我有什么幫助:我在源文件的略微不同的部分手工重寫了這個功能(沒有復制粘貼)。 我也改名,以防萬一。 舊功能的身體被刪除了。 它立即開始正常工作。

我不知道它是什么,但我在生活中遇到過類似的情況,有幾次使用純C語言和Perl語言。

Android Studio。 AOSP 7.1.2前叉。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM