在我的情况下,使用 JNI 调用 CallVoidMethod 时抛出 NPE 的可能原因是什么
What's the possible reason why NPE is throwed when call CallVoidMethod with JNI in my situation
场景:我已经用Cpp构建了一个DLL,它被带有JNI的java应用程序使用。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();
}
到目前为止我尝试过的:
- jmethod的值是而不是零。这意味着我已经找到了Java端的方法。(如果我错了,请纠正我。)
- 两个jclass-cls=env->GetObjectClass(jobj);和jclass-cls=env->FindClass(absolute_path)试图获取jclass信息
堆栈跟踪非常简单,它是:
线程"线程-2"出现异常
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保持从本机端调用。未声明的变量(如env、jobj等)在CaptureCallback.h文件中声明。
与上次提问的答案相同。obj
要么为null,要么在被调用的方法或其调用的方法中,某个东西在为null时被取消引用,依此类推。或者,有人,可能是你给出了一些现在已经删除的代码,出于某种可能无关的原因故意抛出这个异常。
【请注意:这些确实是唯一可能的原因。如果你不同意,请给出你选择的理由。】
遗憾的是,您的代码没有错误检查。您需要检查每个JNI调用的结果,而不仅仅是您喜欢的调用。之前的任何一个都可能抛出NPE。我在上面依赖于你的断言,即它是CallVoidMethod()
,但它可能不是。
为什么你要把一个可能是任何东西的异常变成NullPointerException
是个谜。您应该重新抛出throwable
,而不是抛出一个新的、可能不相关的异常来混淆自己。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- C++避免重复声明的语法是什么
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- C++从另一个类访问公共静态向量的正确方法是什么
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- C++中名称篡改的目的是什么
- 在 c++ 中拥有一组结构的正确方法是什么?
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 是什么阻止DOMTimerCoordinator::NextID进入无休止的循环
- 派生类销毁的最佳实践是什么
- 这个语法std::class<>{}(arg1, arg2) 在C++中是什么意思?
- 通过JNI传递数据数组的最快方法是什么
- "using namespace std;"在C++的作用是什么?
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- 文件系统:复制功能的速度秘诀是什么
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 使用QQuickFramebufferObject时同步数据的最佳方式是什么
- 是什么原因导致它无法编译?它是声明签名还是在函数本身的实现中
- 在我的情况下,使用 JNI 调用 CallVoidMethod 时抛出 NPE 的可能原因是什么