Mon code commence en Java, invoque C++, qui invoque ensuite le Java de retour pour des choses comme trouver, obtenir et la définition de valeurs de champ.
Dans le cas où quelqu'un qui recherche un C++ approche trouve cette page, je vais la charrue avec ceci:
Ce que je suis en train de faire maintenant est d'emballage de mon JNI le corps de méthode avec un C++ bloc try/catch,
JNIEXPORT void JNICALL Java_com_pany_jni_JNIClass_something(JNIEnv* env, jobject self)
{
try
{
... do JNI stuff
// return something; if not void.
}
catch (PendingException e) // (Should be &e perhaps?)
{
/* any necessary clean-up */
}
}
où PendingException est déclaré trivialement:
class PendingException {};
et je suis en invoquant la méthode suivante après avoir invoqué tout JNI à partir de C++, donc si l'exception Java statut indique une erreur, je vais caution immédiatement et laissez-la Java normal de gestion des exceptions ajouter le (Native method) de la ligne de la trace de la pile, tout en donnant le C++ la possibilité de nettoyer tout en vous détendant:
PendingException PENDING_JNI_EXCEPTION;
void throwIfPendingException(JNIEnv* env)
{
if (env->ExceptionCheck()) {
throw PENDING_JNI_EXCEPTION;
}
}
Mon Java trace de la pile ressemble à ça pour un échec de l'env->GetFieldId() appel:
java.lang.NoSuchFieldError: no field with name='opaque' signature='J' in class Lcom/pany/jni/JniClass;
at com.pany.jni.JniClass.construct(Native Method)
at com.pany.jni.JniClass.doThing(JniClass.java:169)
at com.pany.jni.JniClass.access$1(JniClass.java:151)
at com.pany.jni.JniClass$2.onClick(JniClass.java:129)
at android.view.View.performClick(View.java:4084)
et un peu comme si j'appelle à une méthode Java qui lance:
java.lang.RuntimeException: YouSuck
at com.pany.jni.JniClass.fail(JniClass.java:35)
at com.pany.jni.JniClass.getVersion(Native Method)
at com.pany.jni.JniClass.doThing(JniClass.java:172)
Je ne peux pas parler à entourer l'exception Java au sein d'une autre exception Java à partir de C++, je pense que c'est une partie de votre question - je n'ai pas trouvé la nécessité de le faire - mais si je le faisais, je serais soit le faire avec une classe Java wrapper autour de la native méthodes, ou tout simplement de prolonger mon exception des jets de méthodes pour prendre un jthrowable et remplacer l'env->ThrowNew() avec quelque chose de laid: il est malheureux que le Soleil ne fournit pas une version de ThrowNew qui a eu un jthrowable.
void impendNewJniException(JNIEnv* env, const char *classNameNotSignature, const char *message)
{
jclass jClass = env->FindClass(classNameNotSignature);
throwIfPendingException(env);
env->ThrowNew(jClass, message);
}
void throwNewJniException(JNIEnv* env, const char* classNameNotSignature, const char* message)
{
impendNewJniException(env, classNameNotSignature, message);
throwIfPendingException(env);
}
Je ne voudrais pas envisager la mise en cache (exception) constructeur de la classe de références car les exceptions ne sont pas censé être une habitude de contrôle de flux de mécanisme, de sorte qu'il ne devrait pas s'ils sont lents. J'imagine look-up n'est pas terriblement lent de toute façon, depuis Java sans doute fait de son propre mise en cache pour ce genre de chose.