Ошибка шины JNI после перемещения объекта в другой метод - PullRequest
5 голосов
/ 18 января 2010

У меня проблема с 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, и он работает.

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

Ответы [ 2 ]

4 голосов
/ 19 января 2010

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

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

jclass    modelDetailsClass           = NULL;
jmethodID modelDetailsConstMid        = NULL;

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

0 голосов
/ 10 февраля 2012

Этот вопрос отвечает на основную проблему:

Почему я не должен повторно использовать jclass и / или jmethodID в JNI?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...