I'm facing a fatal error when I make a JNI callback from native code:
SIGSEGV ..
Distribution: CentOS release 5.9 (Final), x64
Problematic frame:
V [libjvm.so+0x53499f] JNI_CreateJavaVM+0x20e6f
And the code important to the issue:
JavaVM *JVM;
JavaVMAttachArgs args;
jobject jlistener;
jmethodID callback;
JNIEXPORT void JNICALL JNI_FUNC_NAME(open) (JNIEnv *env, jobject obj, jobject config) {
env->GetJavaVM(&JVM);
args.version = JNI_VERSION_1_6;
args.name = "notifyThread";
args.group = NULL;
// ...
}
JNIEXPORT void JNICALL JNI_FUNC_NAME(setListener) (JNIEnv *env, jobject obj, jobject listener) {
jlistener = env->NewGlobalRef(listener);
jclass thisClass = env->GetObjectClass(listener);
jmethodID callback = env->GetMethodID(thisClass, "messageRx", "(B)V");
// if (NULL == notifyMethod) return;
return;
}
void notify(jbyte x) {
JNIEnv *jniEnv;
int envState = JVM->GetEnv((void **)&jniEnv, 0x00010006);
if(envState == (-2)) {
if(JVM->AttachCurrentThread((void**)&jniEnv, &args) != 0)
jniEnv->ThrowNew(exc, "Could not attach current notifying thread.");
}
jniEnv->CallVoidMethod(jlistener, callback, x); // notify
JVM->DetachCurrentThread();
}
If I comment out the callback line(jniEnv->CallVoidMethod ...
), there is no problem and everything works as expected. The issue is with the actual callback, and, even stranger, on some JVMs it works.
Do you have any idea about this?
The problem was that the callback is used before creating a global reference to the listener object (jlistener
wasn't initialized).