Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to throw exceptions in JNI code?

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?

like image 439
Chris R Avatar asked Oct 23 '08 17:10

Chris R


People also ask

What is Jclass in JNI?

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 {}; ...

Is the exception that clears a pending exception?

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.

What is exception handling in java?

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.


1 Answers

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.

like image 66
Steven M. Cherry Avatar answered Oct 12 '22 23:10

Steven M. Cherry