在我的情况下使用JNI调用CallVoidMethod时,NPE被抛出的可能原因是什么?

时间:2015-12-15 05:38:40

标签: java c++ java-native-interface

方案: 我已经使用Cpp构建了一个DLL,它由Java应用程序与JNI一起使用。 DLL也会在Java中调用方法。但是,当我调用CallVoidMethod时,将在java控制台中打印 java.lang.NullPointerException

代码如下:

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();
}

到目前为止我尝试过:

  1. jmethod的值为零。这意味着我找到了Java方法。(如果我错了,请纠正我。)
  2. 两个jclass cls = env-&gt; GetObjectClass(jobj);和jclass cls = env-&gt;尝试使用FindClass(absolute_path)获取jclass信息。
  3. stacktrace 非常简单,它是:

    线程中的异常&#34;线程-2&#34;

    显示java.lang.NullPointerException

    所以我很难找到原因。

    当前进展: 当我将ACallbackMethod的主体放入Constructor方法时,我设法调用了helloWorld方法。构造函数方法如下所示:

    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();
    }
    

    CaptureCallback是一个继承自IDL生成的头文件的类,并且从本机端保持调用CaptureCallback :: ACallbackMethod。在CaptureCallback.h文件中声明未声明的变量,如env,jobj等。

1 个答案:

答案 0 :(得分:0)

与你上次问的答案相同。 obj为null,或者在被调用方法内部为null时,或者在调用的方法中取消引用某些内容,依次递归。或者,有人,可能你给了一些你现在删除的代码,故意为了一些可能无关的原因抛出这个例外。

[注意到downvoters:这些确实是唯一可能的原因。如果您不同意请提供您选择的理由。]

您的代码可悲地没有错误检查。您需要检查每个JNI呼叫的结果,而不仅仅是您喜欢的呼叫。任何先前的都可以抛弃NPE。我依赖于你的断言它是CallVoidMethod(),但它可能不是。

为什么你要将一个异常变成NullPointerException的异常是一个谜。您应该重新抛出throwable,而不是通过抛出一个新的,可能无关的异常来混淆自己。