tutorial nativos metodos ejemplos jni

nativos - jni tutorial



Cómo atrapar Excepción JNI/Java (2)

Este es un complemento de la respuesta de Elliott Hughes . Mi respuesta proporciona un ejemplo paso a paso que explica cómo detectar excepciones y cómo traducirlas entre palabras C ++ y Java utilizando la capa JNI .

Respuesta corta

Vea la respuesta correcta de Elliott Hughes .

Ejemplo reutilizable

Esta respuesta y los fragmentos están en dominio público o en CC0 para facilitar la reutilización. Todo el código fuente aquí es C ++ 03 compatible con versiones anteriores.

Para reutilizar el fragmento anterior, haga lo siguiente:

  • Reemplace mypackage::Exception por su propia excepción de C ++.
  • Si la excepción de Java correspondiente my.group.mypackage.Exception no está definida, entonces reemplace "my/group/mypackage/Exception" por "java/lang/RuntimeException" .

Captura excepciones de Java

Ver también el fragmento en coliru .

void rethrow_cpp_exception_as_java_exception() { try { throw; // This allows to determine the type of the exception } catch (const mypackage::Exception& e) { jclass jc = env->FindClass("my/group/mypackage/Exception"); if(jc) env->ThrowNew (jc, e.what()); /* if null => NoClassDefFoundError already thrown */ } catch (const std::bad_alloc& e) { jclass jc = env->FindClass("java/lang/OutOfMemoryError"); if(jc) env->ThrowNew (jc, e.what()); } catch (const std::ios_base::failure& e) { jclass jc = env->FindClass("java/io/IOException"); if(jc) env->ThrowNew (jc, e.what()); } catch (const std::exception& e) { /* unknown exception (may derive from std::exception) */ jclass jc = env->FindClass("java/lang/Error"); if(jc) env->ThrowNew (jc, e.what()); } catch (...) { /* Oops I missed identifying this exception! */ jclass jc = env->FindClass("java/lang/Error"); if(jc) env->ThrowNew (jc, "Unidentified exception => " "Improve rethrow_cpp_exception_as_java_exception()" ); } }

Agradezco a Mooing Duck por su contribución al código C ++ anterior.

Adapte el código fuente generado por JNI

El siguiente archivo Java_my_group_mypackage_example.cpp utiliza la función rethrow_cpp_exception_as_java_exception() :

JNIEXPORT jlong JNICALL Java_my_group_mypackage_example_function1 (JNIEnv *env, jobject object, jlong value) { try { /* ... my processing ... */ return jlong(result); } catch(...) { rethrow_cpp_exception_as_java_exception(); return 0; } } JNIEXPORT jstring JNICALL Java_my_group_mypackage_example_function2 (JNIEnv *env, jobject object, jlong value) { jstring jstr = 0 try { /* ... my processing ... */ jstr = env->NewStringUTF("my result"); } catch(...) { rethrow_cpp_exception_as_java_exception(); } return jstr; } JNIEXPORT void JNICALL Java_my_group_mypackage_example_function3 (JNIEnv *env, jobject object, jlong value) { try { /* ... my processing ... */ } catch(...) { rethrow_cpp_exception_as_java_exception(); } }

Código de Java correspondiente

Archivo example.java

package my.group.mypackage; public class Example { static { System.loadLibrary("my-DLL-name"); } public Example() { /* ... */ } private native int function1(int); //declare DLL functions private native String function2(int); //using the keyword private native void function3(int); //''native'' public void dosomething(int value) { int result = function1(value); String str = function2(value); //call your DLL functions function3(value); //as any other java function } }

Nota: " my-DLL-name " se refiere a la biblioteca dinámica producida a partir del código C / C ++ anterior compilado. Puede ser my-DLL-name.dll en Windows o my-DLL-name.so en GNU / Linux / Unix.

Pasos

  1. Genera example.class desde example.java (usando javac o maven o tu IDE favorito Eclipse / Netbeans / IntelliJ IDEA / ...)

  2. Genere el archivo de encabezado C / C ++ Java_my_group_mypackage_example.h de example.class usando javah

Tengo una capa JNI en mi aplicación. En algunos casos, Java arroja una excepción. ¿Cómo puedo obtener la excepción de Java en la capa JNI? Tengo el código algo así como lo siguiente.

if((*(pConnDA->penv))->ExceptionCheck(pConnDA->penv)) { (*(pConnDA->penv))->ExceptionDescribe(pConnDA->penv); (*(pConnDA->penv))->ExceptionClear(pConnDA->penv); }

¿Este bloque de código atrapará solo las excepciones JNI? ¿Dónde se registrará la descripción de la excepción en la consola (stderr)? ¿Cómo puedo obtener esto en el búfer, para poder pasarlo a mi módulo logger?


si invoca un método Java desde JNI, al llamar a ExceptionCheck posteriormente, se devolverá JNI_TRUE si Java arrojó una excepción.

si solo está invocando una función JNI (como FindClass ), ExceptionCheck le dirá si eso falló de una manera que deja una excepción pendiente (como FindClass hará FindClass por error).

ExceptionDescribe salidas a stderr. no hay una manera conveniente de hacerlo funcionar en ningún otro lado, pero ExceptionOccurred te ofrece un jthrowable si quieres jugar con él, o puedes dejarlo subir a Java y manejarlo allí. ese es el estilo habitual:

jclass c = env->FindClass("class/does/not/Exist"); if (env->ExceptionCheck()) { return; } // otherwise do something with ''c''...

tenga en cuenta que no importa qué valor devuelva; el código Java que lo llama nunca lo verá; en su lugar verá la excepción pendiente.