jSegue requires a IRMIFL::jni_env pointer for all JNI
operations. Anywhere a JNI call defines JNIEnv *as a
parameter it is safe to substitute jni_env instead
because jni_env is designed to be cast from a
JNIEnv pointer. If you already have a JNIEnv
pointer you can use the jni_env *jni_cast(JNIEnv *)
function. The form static_cast<jni_env *>(JNIEnv *)
was considered, but we ended up making jni_env privatly derive from
JNIEnv so that the unchecked methods of JNIEnv are hidden.
jSegue thunk methods wrap jSegue impl methods with a try/catch block so
that any java::lang::Throwable * derived exception is
caught and returned to the JVM. jSegue impl methods are passed a jni_env
pointer as their first parameter in a similar way that JNI calls
normally pass JNIEnv pointer.
When a "spontaneous" JNI call must be made there are two
options for obtaining a jni_env pointer. The recommended way is to
declare an auto (local) variable of the type
IRMIFL::jni_local_frame, and then calling its
setup() method, storing the return value into an
IRMIFL::jni_env *. The local reference frame is
popped in ~jni_local_frame, so that when the
jni_local_frame variable goes out of scope all local
reference are deleted.
Additionally, when using a jni_local_frame its a good
practice to declare a try/catch block so that any java exceptions that
have been converted to C++ exceptions can be caught and reported. In
the spontaneous call case these cannot be propagated back to java, but
you can use java.util.logging.Logger or
JNIEnv::ExceptionDescribe to log the exception, including its stack
trace. This sample from OleThread.cpp:
IRMIFL::jni_local_frame lf;
IRMIFL::jni_env &env = *lf.setup(lf);
try {
global_event->dispatch(env);
} catch (Throwable *t) {
env.throw_object(t);
env.exception_describe();
env.exception_clear();
}
Note however, the following code has a serious problem:
if (a_problem_exists) {
IRMIFL::jni_local_frame lf;
throw new(lf.get_env()) RuntimeException(lf.get_env(), "A problem exists");
}
The problem is that the RuntimeException will be
referenced by a JNI local reference that will get deleted when
lf variable goes out of scope. So this code will
throw a local reference that will be deleted before the
exception propagates to the next stack frame.