android - Eccezioni di cattura generate da codice nativo in esecuzione su Android




2 Answers

Avevo lo stesso problema, è vero che in Android (all'interno di qualsiasi VM in generale quando si esegue codice nativo) se si lancia un'eccezione C ++ e questa non viene catturata, la VM muore (se ho capito bene, penso che è il tuo problema). La soluzione che ho adottato era quella di catturare qualsiasi eccezione in C ++ e lanciare un'eccezione java invece di usare JNI. Il prossimo codice è un esempio semplificato della mia soluzione. Prima di tutto hai un metodo JNI che cattura un'eccezione C ++ e quindi nella clausola try l'eccezione Java è annotata.

JNIEXPORT void JNICALL Java_com_MyClass_foo (JNIEnv *env, jobject o,jstring param)
{
    try
    {
        // Your Stuff
        ...
    }
    // You can catch std::exception for more generic error handling
    catch (MyCxxException e)
    {
        throwJavaException (env, e.what());
    }
}


void throwJavaException(JNIEnv *env, const char *msg)
{
    // You can put your own exception here
    jclass c = env->FindClass("company/com/YourException");

    if (NULL == c)
    {
        //B plan: null pointer ...
        c = env->FindClass("java/lang/NullPointerException");
    }

    env->ThrowNew(c, msg);
}

Si noti che dopo un ThrowNew, il metodo nativo non si interrompe bruscamente automaticamente. Cioè, il flusso di controllo ritorna al tuo metodo nativo e la nuova eccezione è in sospeso a questo punto. L'eccezione verrà generata dopo il completamento del metodo JNI.

Spero che sia stata la soluzione che stai cercando.

Il progetto al quale sto lavorando attualmente richiede di codificare la parte Android di un'implementazione di un programma multipiattaforma.

Un insieme di funzionalità di base viene creato e incluso nella mia app tramite android-ndk . Ho scoperto che ogni eccezione / crash che si verifica nel codice nativo viene segnalata solo di tanto in tanto. Quando si verifica un errore, ottengo uno dei seguenti comportamenti:

  • Un dump di memoria / stacktrace si verifica e viene scritto nel file di registro. Il programma scompare (sul dispositivo non viene fornita alcuna indicazione sul motivo per cui improvvisamente l'app non è più lì).
  • Non viene fornito stacktrace / dump o altra indicazione che il codice nativo si sia arrestato in modo anomalo. Il programma scompare.
  • Il codice java si blocca con una NullPointerException (di solito nello stesso posto per eccezione di codice nativo che è un enorme dolore). Di solito mi fa passare un po 'di tempo cercando di eseguire il debug perché il codice Java ha generato un errore solo per scoprire che il codice Java va bene e l'errore del codice nativo è stato interamente mascherato.

Non riesco a trovare alcun modo per "isolare" il mio codice dagli errori che si verificano nel codice nativo. Le dichiarazioni try / catch sono clamorosamente ignorate. A parte il momento in cui il mio codice viene toccato come colpevole, non ho nemmeno la possibilità di avvertire l'utente di un errore.

Qualcuno può aiutarmi a capire come rispondere alla situazione di crash del codice nativo?




Hai preso in considerazione l'idea di intercettare questa eccezione e quindi di includerla in un'eccezione di runtime, solo per farlo salire più in alto nello stack?

Ho usato un simile "hack" in SCJD. Generalmente NPE indica un errore da parte tua, ma se sei convinto che non stai facendo nulla di male, allora crea semplicemente una RuntimeException ben documentata che spiega che l'eccezione è usata per far saltare l'Eccezione. Quindi scartala e prova se per esempio di NPE e gestiscila come tua Eccezione.

Se ciò causerà dati errati, non avrai altra scelta, ma per arrivare alla radice di esso.




Related