Cuando se lanza una excepci�n en Java, la M�quina Virtual busca autom�ticamente el manejador de excepci�n m�s cercano y despliega la pila si es necesario. La ventaja de este estilo de manejo de excepciones es que libera al programador de tener cuidado y del manejo inusual de los errores situados en cada operaci�n del programa. En su lugar, la M�quina Virtual Java propaga autom�ticamente las condiciones del error a la posici�n (la clausula catch de Java) que maneja el mismo tipo de condiciones de error de una forma centralizada.
Mientras que otros lenguajes como C++ soportan una noci�n similar de manejo de excepciones, no existe una manera uniformada de lanzar y capturar excepciones en los lenguajes nativos. Por lo tanto, el JNI requiere que se comprueben las posibles excepciones despu�s de llamar a sus funciones. El JNI tambi�n proporciona funciones que permiten a los m�todos nativos lanzar excepciones Java. Estas excepciones pueden ser manejadas por otras partes del c�digo nativo o por la M�quina Virtual Java. Despu�s de que el c�digo nativo lance o capture una excepci�n, puede eliminar las excepciones pendientes para que el c�lculo contin�e, o puede lanzar otra excepci�n para un manejador exterior.
Muchas funciones JNI pueden lanzar excpeciones. Por ejemplo, la funci�n GetFieldID descrita en la p�gina anterior lanza un NoSuchFieldError si el campo especificado no existe. Para simplificar el chequeo de errores, la mayor�a de las funciones JNI utilizan una combinaci�n de c�digos de error y excepciones Java para informar de las condiciones de error. Por ejemplo, se podr�a chequear si el campo jfieldID devuelto por GetFieldID es cero (0) en vez de llamar a la funci�n JNI ExceptionOccurred. Cuando el resultado de GetFieldID no es cero (0), se puede estar seguro de que no hay una excepci�n pendiente.
El resto de la p�gina ilustra c�mo capturar y lanzar excepciones en c�digo nativo. El c�digo de ejemplo est� en CatchThrow.java.
El m�todo CatchThrow.main llama al m�todo nativo. El m�todo nativo, definido en CatchThrow.c, primero llama al m�todo CatchThrow.callback Java, de esta forma.
jclass cls = (*env)->GetObjectClass(env, obj); jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "()V"); jthrowable exc; if (mid == 0) return; (*env)->CallVoidMethod(env, obj, mid);
Observa que como CallVoidMethod lanza una NullPointerException, el c�digo nativo puede detectar esta excepci�n despu�s de que CallVoidMethod retorne llamando al m�todo ExceptionOccurred.
exc = (*env)->ExceptionOccurred(env); if (exc) {
Como se puede ver es muy sencillo capturar y lanzar una excepci�n. En nuestro ejemplo, no hacemos mucho con la excepci�n en CatchThrow.c excepto utilizar el m�todo ExceptionDescribe para sacar un mensaje de depurado. El m�todo nativo lanza entonces una IllegalArgumentException. Es esta exepci�n IllegalArgumentException es la que ver� el c�digo Java que llam� al m�todo nativo.
(*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException"); if (newExcCls == 0) /* Unable to find the new exception class, give up. */ return; (*env)->ThrowNew(env, newExcCls, "thrown from C code");
La funci�n ThrowNew construye un objeto exception desde una clase exception dada y un string de mensaje y postea la excepci�n en el thread actual.
Observa que es extremadamente importante comprobar, manejar y limpiar las excepciones pendientes antes de llamar a las siguientes funciones JNI. Llamar arbitrariamente a funciones JNI con una excepci�n pendiente podr�a generar resultados inexperados. Solo se pueden llamar de forma segura a unas pocas funciones JNI cuando existe una excepci�n pendiente. Estas funciones son: ExceptionOccurred, ExceptionDescribe, y ExceptionClear.