Search code examples
javac++java-native-interface

What's the possible reason why NPE is throwed when call CallVoidMethod with JNI in my situation


Scenario: I have built a DLL with Cpp which is used by a java applicaton with JNI. The DLL will call method in Java too. However, when I call CallVoidMethod, a java.lang.NullPointerException will be printed in java console.

The code is like below:

void CaptureCallback::ACallbackMethod(){
    jvm->AttachCurrentThread((void **)&env, NULL);
    jmethodID mid= env->GetMethodID(cls, "helloWorld", "()V");
    cout << "The jmethodID is : " << mid << endl;
    cout << "The jobject is : " << jobj << endl;
    cout << "The env is: " << env << endl;
    env->CallVoidMethod(obj, mid );
    jvm->DetachCurrentThread();
}

What I have tried so far:

  1. The value of jmethod is not zero. It means that I have found the method which is in Java side.(Pls correct me if I'm wrong.)
  2. Both jclass cls = env->GetObjectClass(jobj); and jclass cls = env->FindClass(absolute_path) are tried to get jclass info.

The stacktrace is so simple and it is:

Exception in thread "Thread-2"

java.lang.NullPointerException

So it's hard for me to locate the cause.

Current progress: I managed to call the helloWorld method when I put ACallbackMethod's body into the Constructor method. The constructor method is look like:

CaptureCallback::CaptureCallback(JNIEnv *p_env, jobject p_jobj){
        env = p_env;
        jobj = p_jobj;
        jvm->AttachCurrentThread((void **)&env, NULL);
        jmethodID mid= env->GetMethodID(cls, "helloWorld", "()V");
        cout << "The jmethodID is : " << mid << endl;
        cout << "The jobject is : " << obj << endl;
        cout << "The env is: " << env << endl;
        env->CallVoidMethod(obj, mid );   
        jvm->DetachCurrentThread();
}

The CaptureCallback is a class which inherits from an IDL generated header file and the CaptureCallback::ACallbackMethod is kept called from native side.The undeclared variable like env, jobj and so on are declared in CaptureCallback.h files.


Solution

  • Same answer as last time you asked. Either obj is null, or something is dereferenced while null inside the called method, or a method it calls, and so on recursively. Or, someone, possibly you given some of your now-deleted code, is deliberately throwing this exception for some possibly unrelated reason.

    [Note to downvoters: these really are the only possible reasons. If you disagree kindly give reasons for your choice.]

    Your code is lamentably free of error checking. You need to check the result of every JNI call, not just the ones you like. Any of the prior ones could be throwing the NPE. I'm relying above on your assertion that it is the CallVoidMethod(), but it mightn't be.

    Why you're turning an exception which could be anything into a NullPointerException is a mystery. You should rethrow the throwable, not confuse yourself by throwing a new, possibly unrelated exception.