C ++ вызывает метод объекта Java: нарушение прав доступа - PullRequest
1 голос
/ 14 марта 2011

Я пытаюсь реализовать связывание Java / C ++ для класса потоковой передачи звука.Для простоты моего примера я приведу его метод поиска, которого достаточно для описания моей проблемы:

public abstract class JSoundStream extends SoundStream {
    public abstract void seek(float timeOffset);
}

Для тестирования я использую следующую реализацию:

@Override public void seek(float timeOffset) {
    System.out.println("seek(" + timeOffset + ")");
}

Метод seek - это метод обратного вызова, делегированный родными функциями C ++, который служит в качестве обратного вызова для всего, что воспроизводит поток.Изобразите, например, приложение медиаплеера с функцией ускоренной перемотки вперед:

нажата кнопка «Перемотка вперед» -> Потоковая библиотека вызывает обратный вызов C ++ seek -> Метод делегирования на Java seek

Обратите внимание, что это всего лишь пример, не участвует ни поток рассылки событий, ни что-либо еще в стиле фанк.

Когда создается экземпляр JSoundStream, вызывается собственный метод, который сохранитобратно указатель Java VM (JavaVM*), а также ссылку на объект Java (jobject).Я делаю это потому, что не могу контролировать, когда именно вызывается обратный вызов, и я не знаю способа получить среду JNI или объект live без ссылок на Java вообще.Поэтому я сохраняю эту информацию во время создания объекта, где у меня есть ссылки.

Внутри метода C ++ seek я пытаюсь вызвать метод Java seek следующим образом:

virtual void OnSeek(float timeOffset) {
    JNIEnv* env;
    jvm->AttachCurrentThread((void**)&env, NULL);
    env->CallVoidMethod(binding, m_seek, (jfloat)timeOffset);
}

Где binding - это jobject, jvm указатель Java VM и m_seek jmethodID seek метода, который я получил ранее.

Однако этот вызов CallVoidMethod приведет к нарушению доступа в jvm.dll.Все указатели и значения действительны для того, что я могу сказать, и я убедился, что объект Java не получает мусор.Я считаю, что хранение jobject и / или указателя Java VM является источником проблемы, но опять же я не могу понять, почему, поскольку эти значения не меняются во время работы программы.

Может кто-нибудьувидеть проблему в том, как я подхожу к этому?Как иначе - без сохранения ссылок - я бы вызвал объектный метод Java из кода C ++?

1 Ответ

3 голосов
/ 14 марта 2011

Ваш подход должен быть правильным, если

  1. Ваш рабочий объект был получен с binding = env->NewGlobalRef(binding_passed_as_argument);

  2. Вы не звоните AttachCurrentThreadнесколько раз из одного и того же потока - используйте TLS для хранения указателя JNIEnv.

...