I'd like a consistent and simple way to throw exceptions in JNI code; something that handles chained exceptions (implicitly from the env->ExceptionOccurred method, or explicitly by parameters, either way is good) and saves me looking up constructors every time I want to do this. All of the above is preferably in C, although I could translate it from C++ at need.
Does anyone on SO have something like this that they can share?
typedef jobject jclass; In C++, JNI introduces a set of dummy classes to enforce the subtyping relationship. For example: class _jobject {}; class _jclass : public _jobject {}; ...
After the native code catches and handles an exception, it can either clear the pending exception so that the computation may continue, or it can throw another exception for an outer exception handler. Many JNI functions may cause an exception to be thrown.
Java Exception Handling is a mechanism to handle runtime errors such as ClassNotFoundException, IOException, SQLException, RemoteException, etc. Exception is an unwanted or unexpected event, which occurs during the execution of a program, i.e. at run time, that disrupts the normal flow of the program's instructions.
We just code utility methods for each of the types of exceptions we want to throw. Here are some examples:
jint throwNoClassDefError( JNIEnv *env, char *message ) { jclass exClass; char *className = "java/lang/NoClassDefFoundError"; exClass = (*env)->FindClass( env, className); if (exClass == NULL) { return throwNoClassDefError( env, className ); } return (*env)->ThrowNew( env, exClass, message ); } jint throwNoSuchMethodError( JNIEnv *env, char *className, char *methodName, char *signature ) { jclass exClass; char *exClassName = "java/lang/NoSuchMethodError" ; LPTSTR msgBuf; jint retCode; size_t nMallocSize; exClass = (*env)->FindClass( env, exClassName ); if ( exClass == NULL ) { return throwNoClassDefError( env, exClassName ); } nMallocSize = strlen(className) + strlen(methodName) + strlen(signature) + 8; msgBuf = malloc( nMallocSize ); if ( msgBuf == NULL ) { return throwOutOfMemoryError ( env, "throwNoSuchMethodError: allocating msgBuf" ); } memset( msgBuf, 0, nMallocSize ); strcpy( msgBuf, className ); strcat( msgBuf, "." ); strcat( msgBuf, methodName ); strcat( msgBuf, "." ); strcat( msgBuf, signature ); retCode = (*env)->ThrowNew( env, exClass, msgBuf ); free ( msgBuf ); return retCode; } jint throwNoSuchFieldError( JNIEnv *env, char *message ) { jclass exClass; char *className = "java/lang/NoSuchFieldError" ; exClass = (*env)->FindClass( env, className ); if ( exClass == NULL ) { return throwNoClassDefError( env, className ); } return (*env)->ThrowNew( env, exClass, message ); } jint throwOutOfMemoryError( JNIEnv *env, char *message ) { jclass exClass; char *className = "java/lang/OutOfMemoryError" ; exClass = (*env)->FindClass( env, className ); if ( exClass == NULL ) { return throwNoClassDefError( env, className ); } return (*env)->ThrowNew( env, exClass, message ); }
That way, it's easy to find them, your code-completion editor will help you to type them in, and you can pass simple parameters.
I'm sure you could expand this to handle chained exceptions, or other more complicated approaches. This was enough to meet our needs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With