This is a question related to a previous post, but this post was solved and now I wanted to change the direction of the question.
When working with JNI, it is necessary to ask the JNIEnv
object for jclass
and jmethodID
for each class and method that will be used in the C/C++ code. Just to be clear, I want to call Java contructors or methods from C/C++.
Since the communication from Java to C/C++ (and viceversa) is costly, I initially thought that one way to minimize this was to reuse the jclass
and jmethodID
. Therefore, I saved this instances in global variables as follows:
jclass someClass = NULL;
jmethodID someMethod = NULL;
JNIEXPORT jobject JNICALL Java_example_method1(JNIEnv *env, jobject jobj) {
// initialize someClass and someMethod if they are NULL
// use someClass and someMethod to call java (for example, thru NewObject)
}
JNIEXPORT jobject JNICALL Java_example_method2(JNIEnv *env, jobject jobj) {
// initialize someClass and someMethod if they are NULL
// use someClass and someMethod to call java again
}
A more specific (and useful) example, which I use to throw exceptions from anywhere in my JNI functions:
jclass jniExceptionClass = NULL;
void throwJavaException(JNIEnv *env, const char* msg) {
if (!jniExceptionClass) {
jniExceptionClass = env->FindClass("example/JNIRuntimeException");
}
if (jniExceptionClass)
env->ThrowNew(jniExceptionClass, msg);
}
}
The problem is that I continued to use this pattern and got a segmentation fault that was only solved by not-reusing this variables (this was the solution to the previous post).
The questions are:
- Why is it illegal to reuse the
jclass
andjmethodID
thru different JNI functions? I thought that this values were always the same. - Just for curiosity: what is the impact/overhead of initializing all necessary
jclass
andjmethodID
for each JNI function?