Attraper les exceptions levées à partir du code natif en cours d'exécution sur Android
Le projet sur lequel je travaille actuellement sur me demande de code android partie d'une plate-forme de mise en œuvre du programme.
Un ensemble de base de la fonctionnalité est intégrée et inclus dans mon application par le biais d' android-ndk
. J'ai trouvé que toute exception/crash qui se passe dans le code natif n'est rapporté ici et là, au mieux. Lorsqu'une erreur se produit-je obtenir l'un des comportements suivants:
- Une stacktrace /vidage de mémoire se produit et est écrit dans le fichier journal. Le programme disparaît (aucune indication n'est donnée sur le périphérique pourquoi, soudain, l'application n'est plus là).
- Pas stacktrace /dump ou une autre indication est donné que le code natif est tombé en panne. Le programme disparaît.
- Le code java se bloque avec un
NullPointerException
(en général dans le même endroit par du code natif à l'exception de ce qui est une énorme douleur). Habituellement, m'obligeant à passer du temps à essayer de déboguer pourquoi le code Java a jeté une erreur seulement de découvrir le code Java est fine, & le natif de code d'erreur a été entièrement masqué.
Je n'arrive pas à trouver de toute façon à "isoler" mon code à l'encontre des erreurs qui se produisent dans le code natif. Les instructions Try/catch sont amplement ignoré. À part quand mon code est pointé du doigt comme le coupable, je n'ai même pas la chance d'avertir l'utilisateur qu'une erreur s'est produite.
Quelqu'un peut s'il vous plaît aidez-moi comment répondre à la situation de s'écraser en code natif?
- Les tests unitaires, les journaux... Les seules alternatives je sais off (mais je sais faaar de tout, donc s'il vous plaît regardez plus loin 🙂 )
- Contrôlez-vous le code natif à tous? Ou tout simplement la Java côté?
- Seulement le haut de la couche de code natif, c'est à dire la JNI de la couche de Liant.
Vous devez vous connecter pour publier un commentaire.
J'ai utilisé le même problème, il est vrai que dans android (à l'intérieur de toute la VM en général lors de l'exécution de code natif) si vous jetez une des exceptions C++ et celui-ci n'est pas pris, la VM meurt (Si j'ai bien compris, je pense que c'est votre problème). La solution que j'ai adoptée a été d'attraper une exception en C++ et lancer une exception java au lieu de l'utilisation de JNI. Le code suivant est un exemple simplifié de ma solution. Tout d'abord, vous avez un JNI méthode qui attrape l'une des exceptions C++ et ensuite dans l'essai, la clause d'exception Java est annoté.
Noter qu'après un ThrowNew, la méthode native n'a pas brusquement fin automatiquement. C'est, flux de contrôle renvoie à votre méthode native, et la nouvelle exception est en cours à ce moment. L'exception sera levée après votre JNI méthode est fini.
J'espère que c'était la solution que vous cherchez.
EDIT: Voir aussi cette plus élégant répondre.
Ci-dessous mécanisme est basé sur un Préprocesseur C macro que j'ai mis en œuvre avec succès dans un JNI couche.
La macro ci-dessus
CATCH_CPP_EXCEPTION_AND_THROW_JAVA_EXCEPTION
convertit les exceptions C++ en Java exceptions.Remplacer
mypackage::Exception
par vos propres exceptions C++. Si vous n'avez pas défini le correspondantmy.group.mypackage.Exception
en Java, puis remplacez"my/group/mypackage/Exception"
par"java/lang/RuntimeException"
.Le fichier
Java_my_group_mypackage_example.cpp
à l'aide de la macro ci-dessus:Juste pour de l'information ou de la curiosité, je donne ci-dessous le code Java correspondant (fichier
example.java
). Notez le "my-DLL-name
" est au-dessus de code C/C++ compilé sous forme de DLL ("my-DLL-name
" sans le ".dll
" extension). Cela fonctionne aussi parfaitement à l'utilisation de Linux/Unix bibliothèque partagée*.so
.D'abord, générer
example.class
deexample.java
(à l'aide dejavac
ou votre favori IDE ou maven...). Deuxièmement, générer des C/C++ fichier d'en-têteJava_my_group_mypackage_example.h
deexample.class
à l'aide dejavah
.CATCH_CPP_EXCEPTION_AND_THROW_JAVA_EXCEPTION
. Pour localiser la ligne, vous pouvez remplacerCATCH_CPP_EXCEPTION_AND_THROW_JAVA_EXCEPTION
par le code correspondant (sans le ` à la fin de chaque ligne). Bonne chance, merci 😉Avez-vous pensé à la capture de cette exception et puis en l'enveloppant dans une exception d'exécution, juste pour le faire monter plus haut dans la pile?
J'ai utilisé un semblable "hack" dans SCJD. Généralement NPE indique une erreur de votre part, mais si vous êtes convaincu que vous ne faites rien de mal, puis il suffit de faire une bien documenté
RuntimeException
qui explique que l'exception est utilisé pour la bulle de l'Exception. Ensuite déballer et tester si, par exemple, des entrées en phase nationale et de traiter avec elle en tant que votre propre Exception.Si c'est le résultat de données erronées, alors vous n'avez pas d'autre option, mais pour arriver à la racine de celui-ci.
RuntimeException
? Lors du débogage de l'application d'un NPE sera levée lors de l'un .set() (par exemple) est appelé sur une variable qui permet de voir à travers le débogueur et est isolable d'unLog.v()
directement avant le .set() est appelée.try
/catch
. LeNPE
s'rapporté, je pense, un effet secondaire du code natif en train de mourir et ne sont pas directement liés à l'accident en quelque sorte.