Java 将对象创建移动到另一个方法后发生JNI总线错误
我对JNI有一个问题,这让我花了一整天的时间,如果我不寻求帮助,可能会让我发疯 有两个短语:我从JNI方法调用一个新对象,它工作正常,但当我将此代码移动到另一个方法时,它崩溃了 更多详细信息: 我有一个简单的类,我想从JNI C/C++代码中创建它的实例:Java 将对象创建移动到另一个方法后发生JNI总线错误,java,java-native-interface,Java,Java Native Interface,我对JNI有一个问题,这让我花了一整天的时间,如果我不寻求帮助,可能会让我发疯 有两个短语:我从JNI方法调用一个新对象,它工作正常,但当我将此代码移动到另一个方法时,它崩溃了 更多详细信息: 我有一个简单的类,我想从JNI C/C++代码中创建它的实例: package example; public class ModelDetails { public ModelDetails() { ... } } 使用本机方法的类如下所示: package example; public
package example;
public class ModelDetails {
public ModelDetails() { ... }
}
使用本机方法的类如下所示:
package example;
public class JNIWrapper {
public native ModelDetails getModelDetails() throws SomeException;
}
以下代码工作得非常好:
jclass modelDetailsClass = NULL;
jmethodID modelDetailsConstMid = NULL;
JNIEXPORT jobject JNICALL Java_example_JNIWrapper_getModelDetails
(JNIEnv *env, jobject jobj) {
cout << "getModelDetails c++" << endl;
// ModelDetails class
if (!modelDetailsClass) { // reuse class
modelDetailsClass = env->FindClass("example/ModelDetails");
}
if (!modelDetailsClass) { // check if findclass was successful
throwJavaException(env, "Could not get class ModelDetails");
return NULL;
}
cout << "model detail class: " << modelDetailsClass << endl;
// constructor
if (!modelDetailsConstMid) { // reuse method id
modelDetailsConstMid = env->GetMethodID(modelDetailsClass, "<init>", "()V");
}
if (!modelDetailsConstMid) { // check if getmethodid was successful
throwJavaException(env, "Could not get ModelDetails constructor method id");
return NULL;
}
// create object
jobject mdetails = env->NewObject(modelDetailsClass, modelDetailsConstMid);
if (!mdetails) {
throwJavaException(env, "Could not create ModelDetails instance");
return NULL;
}
return mdetails;
}
这样,在Java\u example\ujniwrapper\u getModelDetails
中,我只调用fillModelDetails(env,jobj)代码>
问题是,现在我在NewObject
行得到一个总线错误
Invalid memory access of location 0x9 eip=0x475fe1
问题:
有人知道为什么我不应该从另一个方法调用构造函数吗?看起来真的很奇怪
谢谢你的任何提示、想法、评论
编辑:
我刚刚添加了-Xcheck:jni
,出现以下错误:
FATAL ERROR in native method: Bad global or local ref passed to JNI
at example.JNIWrapper.getModelDetails(Native Method)
这让我想到问题可能是由使用全局变量的构造函数和类id引起的。我将这些声明移动到JNI方法中的一个局部变量中,它可以工作
这真的让我吃惊,因为我从一段时间以来一直在使用这些全局变量,从来没有遇到过任何问题。。。是什么导致了这个问题?我会回答这个问题,因为我发现了这个问题,但是关于重新使用jclass
和jmethodID
还有另一个问题。向那个方向改变这个问题似乎没有条理,所以我将打开另一个线程
解决的办法是使用局部变量
jclass modelDetailsClass = NULL;
jmethodID modelDetailsConstMid = NULL;
而不是我以前使用的全局变量。这个问题回答了根本问题:
您应该附加一个调试器,并找出错误的确切位置。我这样做了,正是在NewObject调用时。env、modelDetailsClass和mid的值是多少?“9”表示env中的0。它确实是@YuppieNetworking在其自己的回答中提到的“[an]另一个线程:-”)您几乎正确地观察到了它:但jmethodID不是问题所在,它始终是相同的整数值,您可以将其存储在静态变量中。这个问题只是由JNI代码返回Java时垃圾收集的jclass引起的,而且您没有深入研究为什么它只工作一次而另一次失败。如果在一个函数或另一个函数中执行代码,则与此无关。原因是您离开了JNI代码,返回Java,在Java中运行垃圾收集器,然后在静态jclass变量不再有效的地方再次调用JNI。问题的原因是,在静态C++变量中存储JC类(它是垃圾收集)的本地引用。所有本地引用仅对一个JNI函数调用有效。当JNI返回Java时,所有本地引用都将无效。
jclass modelDetailsClass = NULL;
jmethodID modelDetailsConstMid = NULL;