Wednesday, January 16, 2008

Functions with a Variable Argument List II

After using functions with a variable argument list to implement a simple logging sollution I found out that those functions do a great job also in the exception handling.
When you want to throw an exception you usually implement a utility method like this:

void throwByName(JNIEnv *env, const char *name, const char *msg)
{
env->ExceptionDescribe();
env->ExceptionClear();

jclass cls = env->FindClass(name);
/* if cls is NULL, an exception has already been thrown */
if (cls != NULL)
{
env->ThrowNew(cls, msg);
}
/* free the local ref */
env->DeleteLocalRef(cls);
}


This method can be invoked in such a way:
char buffer[128];
throwByName(env, "com/exceptions/MyException", buffer);

The problem is that if you have a lot of methods and exception condition you have to copy/paste every time the exception class that is inconvenient. Also after the first refactoring you'll probably have to change the exception class on so much places.
To avoid those problems you can implement utility methods for all the exceptions that are used (or maybe the most often used) to store the exception class:
void throwMyException(JNIEnv * env, const char * errorMessage, ...)
{
char buffer[STACK_TRACE_SIZE];
va_list args;
va_start(args, errorMessage);
vsnprintf(buffer, sizeof(buffer), errorMessage, args);

throwByName(env, "com/exceptions/MyException", buffer);
}

The benefit is that you can throw that particular exception very easy and without much copy/paste:
throwMyException(env, "Error finishing encryption!");

You can also take a look at this post for more tips&trick for JNI.

No comments: