Mi código comienza en Java, invoca C++, que a su vez invoca Java volver de nuevo para cosas como encontrar, conseguir y configuración valores de campo.
En caso de que alguien en busca de un C++ enfoque encuentra esta página, voy a arar con esto:
lo que ahora estoy haciendo está envolviendo mis cuerpos de los métodos JNI con un C++ 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 */
}
}
donde PendingException se declara trivialmente:
class PendingException {};
y estoy invocando el método siguiente después de invocar cualquier JNI de C++, por lo que si el estado de excepción de Java indican Es un error, voy a rescatar de inmediato y dejar que el manejo normal excepción de Java añadir la línea (método nativo) para el seguimiento de la pila, al tiempo que el C++ la oportunidad de limpiar mientras se relajan:
PendingException PENDING_JNI_EXCEPTION;
void throwIfPendingException(JNIEnv* env)
{
if (env->ExceptionCheck()) {
throw PENDING_JNI_EXCEPTION;
}
}
Mi pila de Java rastro parece que esto para un env> GetFieldID() llamada fallida:
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)
y bastante similares si llamo a un método Java que arroja:
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)
no puedo hablar con envoltura la excepción de Java dentro de otra excepción de Java desde dentro de C++, que creo que es parte de su pregunta, no he encontrado la necesidad de hacerlo, pero si lo hiciera, lo haría con un envoltorio de nivel Java alrededor del métodos nativos, o simplemente extender mis métodos de lanzamiento de excepciones para tomar un jthrowable y reemplazar el env-> ThrowNew() llamada con algo feo: es desafortunado que Sun no haya proporcionado una versión de ThrowNew que haya sido eliminada.
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);
}
no consideraría referencias almacenamiento en caché (excepción) constructor de la clase porque las excepciones no se supone que es un mecanismo de control de flujo de costumbre, por lo que no debería importar si son lentos. Me imagino que la búsqueda no es terriblemente lenta de todos modos, ya que Java presumiblemente hace su propio almacenamiento en caché para ese tipo de cosas.
Por 'maneja excepciones encadenadas' ¿quiere decir que su código notará una excepción de nivel Java al regresar de Java a C++, lo envuelve en alguna otra excepción y lanza esa nueva excepción desde C++ a Java? –