2016-10-17 11 views
0

AndroidのネイティブC++コードでエラーをキャッチしようとしています。ドキュメントによるとFindClassはクラス名が見つからないときにNULLを返します。しかし、私はFATAL EXCEPTION: main java.lang.NoClassDefFoundError: fake/classを得て、実行は決してifステートメントに達しません。Android NDK C++コードで例外をキャッチ

#include <string.h> 
#include <jni.h> 

extern "C" 
void Java_com_example_MainActivity_testError(JNIEnv *env, jobject) { 
    jclass clazz = env->FindClass("fake/class"); 
    // never gets here 
    if (clazz == NULL) { 
     return; 
    } 
} 

また、この例外はtry-catchブロックをスキップし、アプリケーションをクラッシュさせます。私のJavaコード:

static { 
    System.loadLibrary("native-lib"); 
} 

public native void testError(); 

... 
try { 
    testError(); 
} catch (Exception e) { 
    // exception never get cought 
} 

また、cppFlags '-fexceptions'を使用します。この例外をキャッチするか、アプリからクラッシュしないように回復する適切な方法はありますか?

+0

https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#FindClassスロー:NoClassDefFoundError:要求されたクラスまたはインタフェースの定義が見つからない場合。 JNIには、Java例外がスローされて処理されているかどうかを調べるメソッドがあります。 Java例外は、JNIメソッドが返されるまで「アクティブになる」ことはありません。 –

+0

java.lang.NoClassDefFoundErrorはjava.lang.Exceptionからではなくjava.lang.Errorから派生しています。そのため、あなたの例外は捕捉されていません。 https://docs.oracle.com/javase/7/docs/api/java/lang/NoClassDefFoundError.html –

+0

を参照してください。「-fexceptions」フラグについて言及しているので、JavaとC++の例外を混同しないでください。別の獣。 – zenzelezz

答えて

0

あなたはすべてのJNI呼び出しの後、このコードを使用する必要がありますなど、FindClassが上のクラッシュからネイティブコードを防ぐために、まず:

bool checkExc(JNIEnv *env) { 
    if (env->ExceptionCheck()) { 
     env->ExceptionDescribe(); // writes to logcat 
     env->ExceptionClear(); 
     return true; 
    } 
    return false; 
} 

実は、ExceptionClear()がクラッシュを停止します。私はこの回答のコードを見つけましたhttps://stackoverflow.com/a/33777516/2424777

第2に、ネイティブコードからすべてのクラッシュを確実に捕まえるためには、このtry-catchを使用する必要があります。クレジット@Richard Crittenはまた、すべてのネイティブ関数でそれを使用するコール:

static { 
    try { 
     System.loadLibrary("native-lib"); 
    } catch (Error | Exception ignore) { } 
} 

とCPPFLAGS「-fexceptions」をあなたがそれを削除することができますので、それを行うには何もしています。