У меня проблема с 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;
}
ThisКстати, в Java_example_JNIWrapper_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)
Так что это дало мне идею, что проблема может быть вызвана использованием конструктора и идентификатора класса из глобальной переменной.Я переместил эти объявления в локальную переменную в методе JNI, и он работает.
Это действительно удивляет меня, потому что я использую эти глобальные переменные с некоторого времени и никогда не было проблем ... что может бытьвызывает эту проблему?