Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the message from a Java exception caught in JNI

I am attempting to catch exceptions being thrown by Java and report the exception message to my own logging framework. However, if I do this, there's an obvious chicken-and-egg problem; I'm trying to get the message using the Java getMessage() call:

jthrowable e = env->ExceptionOccurred();
jclass clazz = env->GetObjectClass(e);
jmethodID getMessage = env->GetMethodID(clazz,
                                        "getMessage",
                                        "()Ljava/lang/String;");

but I can't actually resolve getMessage, because the pending exception causes the JVM to abort when I call GetObjectClass.

Is there a safe way to get the jmethodID for all exceptions up-front? If I Just get the method ID for Throwable.getMessage() at application startup, will that jmethodID be portable to other classes? Or is the appropriate approach to call env->ExceptionClear() and just keep on using the same local jthrowable reference?

like image 700
fluffy Avatar asked Nov 22 '14 00:11

fluffy


People also ask

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.

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.


1 Answers

The below works; however, I don't know if it's the intended-correct approach:

jthrowable e = env->ExceptionOccurred();
env->ExceptionClear(); // clears the exception; e seems to remain valid

jclass clazz = env->GetObjectClass(e);
jmethodID getMessage = env->GetMethodID(clazz,
                                        "getMessage",
                                        "()Ljava/lang/String;");
jstring message = (jstring)env->CallObjectMethod(e.get(), getMessage);
const char *mstr = env->GetStringUTFChars(message, NULL);
// do whatever with mstr
env->ReleaseStringUTFChars(message, mstr);
env->DeleteLocalRef(message);
env->DeleteLocalRef(clazz);
env->DeleteLocalRef(e);
like image 111
fluffy Avatar answered Oct 28 '22 00:10

fluffy