Intereting Posts
Android: две ошибки только иногда / на некоторых устройствах Удалите изображение из приложения для просмотра изображений Android Связь Android между двумя действиями в одном пакете Android: рисование растрового изображения в определенном месте, отказ от рисования Android WiFi Direct Discovery и время работы от батареи RecyclerView с фиксированным столбцом и заголовком, плюс прокручиваемый нижний колонтитул Как получить libcap (библиотека возможностей Linux) для Android? Низкое качество изображения / изображения при захвате с камеры Файлы вкуса и ресурсов Android Intellij не может запускать приложение в Genymotion (но может запустить его) Lollipop: уведомление о хедз-ап отменяется при нажатии Переопределить имя пакета Android для отчетов Crashlytics Android isScreenOn Nullpointerexception Смешивание пикселей из двух растровых изображений Soft Keyboard открывается, затем закрывается нажатием кнопки edittext

JNI – вызов метода Java из C ++

Поэтому я пытался вызвать Java-метод из C ++ без везения. Это ошибка, которую я получаю:

JNI ERROR (ошибка приложения): доступ к устаревшей локальной ссылке 0x5cb00019 (индекс 6 в таблице размера 2) VM прерывание Фатальный сигнал 11 (SIGSEGV) на 0xdeadd00d (код = 1)

Вот что я делаю в коде (java-side):

public class Wrapper extends Activity{ private native void initJNIBridge(); static final String TAG = "Wrapper"; protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); initJNIBridge(); // Calls C++ function. } public void upgradeAdFree() { Log.d(TAG, "Wrapper::upgradeAdFree()"); } 

И вот сторона C ++:

  typedef struct JniMethodInfo_ { JNIEnv * env; jclass classID; jmethodID methodID; } JniMethodInfo; extern "C" { static jobject javaObj; // get env and cache it static JNIEnv* getJNIEnv(void) { JavaVM* jvm = cocos2d::JniHelper::getJavaVM(); if (NULL == jvm) { LOGD("Failed to get JNIEnv. JniHelper::getJavaVM() is NULL"); return NULL; } JNIEnv *env = NULL; // get jni environment jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4); switch (ret) { case JNI_OK : // Success! return env; case JNI_EDETACHED : // Thread not attached // TODO : If calling AttachCurrentThread() on a native thread // must call DetachCurrentThread() in future. // see: http://developer.android.com/guide/practices/design/jni.html if (jvm->AttachCurrentThread(&env, NULL) < 0) { LOGD("Failed to get the environment using AttachCurrentThread()"); return NULL; } else { // Success : Attached and obtained JNIEnv! return env; } case JNI_EVERSION : // Cannot recover from this error LOGD("JNI interface version 1.4 not supported"); default : LOGD("Failed to get the environment using GetEnv()"); return NULL; } } // get class and make it a global reference, release it at endJni(). static jclass getClassID(JNIEnv *pEnv) { jclass ret = pEnv->FindClass(CLASS_NAME); if (! ret) { LOGD("Failed to find class of %s", CLASS_NAME); } return ret; } static bool getMethodInfo(JniMethodInfo &methodinfo, const char *methodName, const char *paramCode) { jmethodID methodID = 0; JNIEnv *pEnv = 0; bool bRet = false; do { pEnv = getJNIEnv(); if (! pEnv) { break; } jclass classID = getClassID(pEnv); methodID = pEnv->GetMethodID(classID, methodName, paramCode); if (! methodID) { LOGD("Failed to find method id of %s", methodName); break; } methodinfo.classID = classID; methodinfo.env = pEnv; methodinfo.methodID = methodID; bRet = true; } while (0); return bRet; } JNIEXPORT void JNICALL Java_org_test_games_Wrapper_initJNIBridge(JNIEnv *, jobject jobj){ LOGD("Java_org_test_games_Wrapper_initJNIBridge()"); javaObj = jobj; return; } void upgradeAdFreeJNI() { LOGD("upgradeAdFreeJNI"); JniMethodInfo methodInfo; if (! getMethodInfo(methodInfo, "upgradeAdFree", "()V")) { LOGD("Cannot find method!"); return; } methodInfo.env->CallVoidMethod(javaObj, methodInfo.methodID); } } 

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

благодаря

Проблема в том, что ваш статический указатель на ваш jobject больше не действителен. Вам нужно защитить его от любых сборок сборщиков мусора. Это можно сделать, используя глобальные ссылки вместо локальных. Вместо того, чтобы просто назначать указатель, создайте globalRef.

 JNIEXPORT void JNICALL Java_org_test_games_Wrapper_initJNIBridge(JNIEnv *, jobject jobj) { LOGD("Java_org_test_games_Wrapper_initJNIBridge()"); javaObj = env->NewGlobalRef(env, jobj); return; } 

Но имейте в виду, что вы также должны освободить globafRef.

Вы не должны просто хранить указатель на объект, как говорит ваша ошибка. Когда вы хотите сохранить его, вам необходимо сохранить локальную или глобальную ссылку на объект. См. http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/functions.html#global_local

Изменить на:

  JNIEXPORT void JNICALL Java_org_test_games_Wrapper_initJNIBridge(JNIEnv *env, jobject jobj){ LOGD("Java_org_test_games_Wrapper_initJNIBridge()"); javaObj = NewGlobalRef(env, jobj); return; }