2016-10-17 2 views
0

Я пытаюсь поймать ошибку в собственном C++-коде на Android. Согласно документам 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 THROWS: 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

Во-первых, чтобы предотвратить машинный код от аварии на FindClass и т.д., вы должны использовать этот код после каждого вызова JNI:

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

Во-вторых, убедитесь, что поймали все сбои из собственного кода, вы должны использовать этот try-catch. Кредиты @Richard Critten также использовать его на все нативные вызовы функций:

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

И «-fexceptions» CPPFLAGS не имеет ничего, чтобы сделать это, так что вы можете удалить его.