web-dev-qa-db-ja.com

AndroidアプリケーションでJNIがエラーを検出:保留中の例外でJNI GetMethodIDが呼び出されました

AndroidプロジェクトでGoogleのOCR Tesseractを実行しようとしています。Android-ndkですでにtesseractに準拠しており、Androidプロジェクト。

私の環境は次のとおりです

  • Android 5.1.1
  • WindowsのAndroid-ndk-r10e
  • Android-sdk-r22

参考までに、ここにリストされている例からビルドしています Example Link

前もって感謝します!

ここに私のlogcat結果のスニペットがあります:

  I/DEBUG   (  182): Revision: '0'
    I/DEBUG   (  182): ABI: 'arm'
    I/DEBUG   (  182): pid: 20291, tid: 20337, name: JavaBridge  >>> com.enterprisem
    obility.OCR <<<
    I/DEBUG   (  182): signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
    I/DEBUG   (  182): Abort message: 'art/runtime/check_jni.cc:65] JNI DETECTED ERR
    OR IN APPLICATION: JNI GetMethodID called with pending exception 'Java.lang.NoSu
    chFieldError' thrown in void com.googlecode.tesseract.Android.TessBaseAPI.native
    ClassInit():-2'
    I/DEBUG   (  182):     r0 00000000  r1 00004f71  r2 00000006  r3 00000000
    I/DEBUG   (  182):     r4 a0701db8  r5 00000006  r6 0000000b  r7 0000010c
    I/DEBUG   (  182):     r8 00000000  r9 b486f520  sl a1c0ac00  fp 00000001
    I/DEBUG   (  182):     ip 00004f71  sp a07006d8  lr b6e503c5  pc b6e72f6c  cpsr
    60070010
    I/DEBUG   (  182):
    I/DEBUG   (  182): backtrace:
    I/DEBUG   (  182):     #00 pc 00039f6c  /system/lib/libc.so (tgkill+12)
    I/DEBUG   (  182):     #01 pc 000173c1  /system/lib/libc.so (pthread_kill+52)
    I/DEBUG   (  182):     #02 pc 00017fd3  /system/lib/libc.so (raise+10)
    I/DEBUG   (  182):     #03 pc 00014795  /system/lib/libc.so (__libc_Android_abor
    t+36)
    I/DEBUG   (  182):     #04 pc 00012f44  /system/lib/libc.so (abort+4)
    I/DEBUG   (  182):     #05 pc 00228cd7  /system/lib/libart.so (art::Runtime::Abo
    rt()+170)
    I/DEBUG   (  182):     #06 pc 000a7371  /system/lib/libart.so (art::LogMessage::
    ~LogMessage()+1360)
    I/DEBUG   (  182):     #07 pc 000b1b17  /system/lib/libart.so (art::JniAbort(cha
    r const*, char const*)+1118)
    I/DEBUG   (  182):     #08 pc 000b2055  /system/lib/libart.so (art::JniAbortF(ch
    ar const*, char const*, ...)+68)
    I/DEBUG   (  182):     #09 pc 000b530f  /system/lib/libart.so (art::ScopedCheck:
    :ScopedCheck(_JNIEnv*, int, char const*)+1346)
    I/DEBUG   (  182):     #10 pc 000b7755  /system/lib/libart.so (art::CheckJNI::Ge
    tMethodID(_JNIEnv*, _jclass*, char const*, char const*)+36)
    I/DEBUG   (  182):     #11 pc 001332f7  /data/app/com.enterprisemobility.OCR-1/l
    ib/arm/libtess.so (Java_com_googlecode_tesseract_Android_TessBaseAPI_nativeClass
    Init+46)
    I/DEBUG   (  182):     #12 pc 0000614d  /data/dalvik-cache/arm/data@[email protected]
    [email protected]@classes.dex
    W/ActivityManager(  536):   Force finishing activity 1 com.enterprisemobility.OC
    R/.MainActivity
    I/DEBUG   (  182):
    I/DEBUG   (  182): Tombstone written to: /data/tombstones/tombstone_07
7
Errol Green

Abortメッセージは比較的明確です。この関数に渡すクラスに存在しないフィールド名に対してGetFieldID(cls, fieldName)を呼び出しますただし、そのエラーはチェックせず、他のJNI関数を引き続き呼び出します。残念ながら、そのようなエラーは無視できません。あなたはmustを呼び出す前にExceptionClear()を呼び出す必要がありますGetMethodID()またはmostのJNI関数。

addr2lineを使用して、クラッシュしたgetMethodID()への特定の呼び出しを見つけ、これに基づいて、失敗したGetFieldID(cls, fieldName)への呼び出しを導き出すことができます。ただし、明日他の関数が例外をスローする可能性があるため、すべてのJNI呼び出しにエラーチェックを追加することをお勧めします。

7
Alex Cohn

私は同じ問題を抱えており、2日間混乱します。最後に、間違ったオブジェクトタイプを渡したことが原因です。たとえば、Javaコードは

public OverlayLine(int mWidth,List<GeoPoint> mPoints);

そして私は以下のようにjniメソッドを登録します:

gClass.mInitMethod = env->GetMethodID(gObject, "<init>", "(ILjava/lang/Object;)V");

エラーメッセージが表示され、エラーが発生します。コードを修正します

gClass.mInitMethod = env->GetMethodID(gObject, "<init>", "(ILjava/util/List;)V");

エラーはなくなりました。「Ljava/lang/Object;」ではなく、正確なオブジェクトタイプを渡す必要があります。

3
choufucai

おそらく、JNIマッピングがC++コードで誤って定義されていました。 JNIは、Javaとの型マッピングに関して非常に厳密な契約を結んでいます。たとえば、JNIからJavaオブジェクトのメソッドを呼び出す前に、その署名が必要です。したがって、メソッドは次のとおりです。

long myMethod (int n, String s, int[] arr);

署名付きのJNIから見られる:

(ILJAVA/LANG/STRING;[I])J

これらのルールの非常に包括的な概要については、こちらをご覧ください。 http://www.rgagnon.com/javadetails/Java-0286.html

0
IgorGanapolsky

Android NDKでndk-stackツールを使用して、クラッシュした位置を見つける必要があります。 ndkスタック に関するリンクを参照してください。

adb logcat > /tmp/foo.txt

$NDK/ndk-stack -sym $PROJECT_PATH/obj/local/armeabi -dump foo.txt
0
HungNM2