How to catch JNI/Java Exception

Viewed 48676

I have a JNI layer in my application. In some cases Java throws an exception. How can I get the Java exception in the JNI layer? I have the code something like as follows.

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

Will this block of code catch only JNI exceptions? Where will the exception description be logged in console(stderr)? How do I get this into the buffer, so that I can pass it to my logger module?

3 Answers

if you invoke a Java method from JNI, calling ExceptionCheck afterwards will return JNI_TRUE if an exception was thrown by the Java.

if you're just invoking a JNI function (such as FindClass), ExceptionCheck will tell you if that failed in a way that leaves a pending exception (as FindClass will do on error).

ExceptionDescribe outputs to stderr. there's no convenient way to make it go anywhere else, but ExceptionOccurred gives you a jthrowable if you want to play about with it, or you could just let it go up to Java and handle it there. that's the usual style:

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

note that it doesn't matter what value you return; the calling Java code will never see it --- it'll see the pending exception instead.

In the case, when the Java exception occurs in a nested C++ call, it's not done with a simple return, but you prefer to remove the intermediate stack levels according to the throw mechanism.

I solved this with a

class JavaException : public std::exception
{
};

Then in a nested call, where the exception is raised

void nestedMethod()
{
    env->CallVoidMethod(...); // Java call creating Exception
    if (env->ExceptionCheck())
    {
        throw JavaException();
    }
}

Finally returning to Java

void JNI_method(JNIenv *env)
{
    try
    {
        doComplexCall(); // --> nestedMethod()
    }
    catch(const JavaException&)
    {
        //coming from positive ExceptionCheck()
        return;
    }
}
Related