Search code examples
javac++callbackjava-native-interface

Runtime error on JNI callback


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?


Solution

  • The problem was that the callback is used before creating a global reference to the listener object (jlistener wasn't initialized).