У меня проблема с JNI, которая заняла у меня весь день и, вероятно, сбила бы меня с ума, если я не позвоню на помощь.Ошибка шины JNI после создания движущегося объекта до другого метода
В двух фразах: Я вызываю объект NewObject из JNI-метода, и он отлично работает, но когда я переместил этот код на другой метод, он сработает.
Подробнее:
У меня есть этот простой класс, и я хочу, чтобы создать ее экземпляры из кода JNI C/C++:
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_example_JNIWrapper_getModelDetails
, я решил перенести создание этого объекта в другую функцию:
jobject fillModelDetails(JNIEnv *env, jobject jobj) {
cout << "fillModelDetails" << 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_example_JNIWrapper_getModelDetails
я просто называю fillModelDetails(env, jobj);
Проблема в том, что теперь я получаю ошибку шины на линии NewObject
.
Invalid memory access of location 0x9 eip=0x475fe1
Вопрос: Кто-нибудь знает, почему я не должен вызвать конструктор из другого метода? Кажется, это действительно странно.
Спасибо за любой совет, идеи, комментарии ...
Edit:
Я просто добавил -Xcheck:jni
и получил эту ошибку:
FATAL ERROR in native method: Bad global or local ref passed to JNI
at example.JNIWrapper.getModelDetails(Native Method)
Так что это дал мне понять, что проблема может быть вызвана использованием конструктора и идентификатора класса из глобальной переменной. Я переместил эти объявления в локальную переменную в JNI-методе, и он работает.
Это действительно удивляет меня, потому что я использовал эти глобальные переменные с некоторого времени и никогда не испытывал никаких проблем ... что может вызвать эту проблему?
Вы должны прикрепить отладчик и выяснить, где именно вы получаете ошибку. – bmargulies
Я сделал это, это точно в вызове NewObject. – YuppieNetworking
Каковы были значения env, modelDetailsClass и mid? что '9' предлагает 0 в env. – bmargulies