【问题标题】:Call Java method from JNI after callback is received收到回调后从 JNI 调用 Java 方法
【发布时间】:2015-04-15 11:37:57
【问题描述】:

我正在构建一个 JNI 应用程序。

从我的 JNI 代码中,我想调用一个更新 UI 的 java 函数。

基本上,当我收到回调并尝试获取对环境的引用时,我会收到以下类型的错误: Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread 1869 (ALooper)

我读到静态引用环境不好,但我可以静态引用 JavaVM

你能告诉我我做错了什么吗?

非常感谢您的宝贵时间

jclass globalClass = NULL;
static JavaVM* mVm = NULL;

jint JNI_OnLoad(JavaVM* vm, void* reserved) {
    mVm = vm;
    JNIEnv* env;

    if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        __android_log_print(ANDROID_LOG_DEBUG, "nativeTAG", "get env failed");
        return -1;
    }
    return JNI_VERSION_1_6;
}

static void callMyJavaFunction() {
    JNIEnv* env;
    jclass playerUtils = NULL;
    jmethodID updatePlayerStatus = NULL;
    jobject myObject = NULL;

    if ((*mVm)->GetEnv(mVm, (void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        __android_log_print(ANDROID_LOG_DEBUG, "jajaja", ">>NATIVE jni failed");

        /*ERROR A/libc(1853): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread 1869 (ALooper)*/
    }

    playerUtils = (*env)->FindClass(env,
        "com/example/customviewcircles/nativeaudio/PlayerUtils");

    if (playerUtils != NULL) {
        updatePlayerStatus = (*env)->GetMethodID(env, playerUtils,
            "updatePlayerStatus", "()V");

        if (updatePlayerStatus != NULL) {
            myObject = (*env)->NewObject(env, playerUtils, updatePlayerStatus);

            (*env)->CallVoidMethod(env, myObject, updatePlayerStatus);
        }
    }
 }

 void myCallBackFunction() {
     callMyJavaFunction();
 }

【问题讨论】:

  • 段错误到底发生在哪里?当你打电话给FindClass..?
  • 回调是否出现在未连接到 VM 的线程上?如果是这样,GetEnv 将返回 JNI_EDETACHED 并且 env 将无效。在这种情况下,您需要致电AttachCurrentThread(以及在您使用完env 之后再致电DetachCurrentThread)。
  • 我得到日志 >>NATIVE jni failed 然后 FindClass() 上的错误
  • 然后看我的第二条评论。
  • 你说得对,我可以再问你一件事,我没有创建另一个线程,为什么回调会在不同的线程上执行?

标签: java android callback java-native-interface ansi-c


【解决方案1】:

在一个聪明的伙伴告诉我我的方法之后。

万一有人需要:

jclass globalClass = NULL;
static JavaVM* mVm = NULL;

jint JNI_OnLoad(JavaVM* vm, void* reserved) {

    mVm = vm;

    JNIEnv* env;
    jclass playerUtils = NULL;

    if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        __android_log_print(ANDROID_LOG_DEBUG, "jajaja", ">>NATIVE jni failed");
        return -1;
    }
    playerUtils = (*env)->FindClass(env,
            "com/example/customviewcircles/nativeaudio/PlayerUtils");

    if (playerUtils != NULL) {

        globalClass = (*env)->NewGlobalRef(env, playerUtils);
    }
    return JNI_VERSION_1_6;
}

void callMyJavaFunction() {

    JNIEnv* env;
    jmethodID updatePlayerStatus = NULL;
    jobject myObject = NULL;

    if((*mVm)->AttachCurrentThread(mVm, &env, NULL) == JNI_OK) {
        __android_log_print(ANDROID_LOG_DEBUG, "jajaja", ">>NATIVE attached successfully");
    }

    if (globalClass != NULL) {

        __android_log_print(ANDROID_LOG_DEBUG, "jajaja",
                            ">>NATIVE globalclass not null");

        updatePlayerStatus = (*env)->GetMethodID(env, globalClass,
                "updatePlayerStatus", "()V");

        if (updatePlayerStatus != NULL) {

            myObject = (*env)->NewObject(env, globalClass, updatePlayerStatus);
        }
    }
    (*mVm)->DetachCurrentThread(mVm);

}

 void myCallBackFunction() {
     callMyJavaFunction();
 }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多