Ошибка шины JNI после перемещения создания объекта к другому методу

У меня есть проблема с JNI, который весь день брал меня и будет, вероятно, управлять мной безумный, если я не зову на помощь.

В двух фразах: Я называю NewObject из метода JNI, и он хорошо работает, но когда я переместил этот код в другой метод, он отказывает.

Подробнее:

У меня есть этот простой класс, и я хочу создать экземпляры его из кода C/C++ JNI:

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

Вопрос: кто-либо знает, почему я не должен вызывать конструктора из другого метода? Это кажется действительно странным.

Спасибо за любую подсказку, идею, комментарии...


Править:

Я только что добавил -Xcheck:jni и получил эту ошибку:

FATAL ERROR in native method: Bad global or local ref passed to JNI
at example.JNIWrapper.getModelDetails(Native Method)

Таким образом, это дало мне идею, что проблема могла бы быть вызвана при помощи конструктора и идентификатора класса от глобальной переменной. Я переместил эти объявления в локальную переменную в методе JNI, и он работает.

Это действительно удивляет меня, потому что я использовал эти глобальные переменные с некоторого времени теперь и никогда не имел проблем..., что могло вызывать эту проблему?

5
задан YuppieNetworking 18 January 2010 в 23:30
поделиться

1 ответ

[11294764-

Я отвечу на это, поскольку я нашел проблему, однако еще один вопрос остается относительно повторной использования JClass и jmethodid . Изменение этого вопроса в этом направлении не кажется организованным, поэтому я открою еще одну поток.

Решение было использование локальных переменных для

jclass    modelDetailsClass           = NULL;
jmethodID modelDetailsConstMid        = NULL;

вместо глобальных переменных, которые я использовал раньше.

4
ответ дан 15 December 2019 в 01:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: