簡體   English   中英

Android:從cpp線程調用static java方法時出現異常

[英]Android: Exception when calling a static java method from cpp thread

當我的 java class 加載時,我調用此 jni 方法將“偵聽器”從 cpp 設置為 java(我使用 cpp 錄制音頻並希望將其字節傳遞給 java):

我的Java.class

setListener(JNIEnv *env, jclass thiz);

我的Cpp.cpp

setListener(JNIEnv *env, jclass thiz) {
    envMyClass = env;
    classMyClass = thiz;
    // I read that I need these 2 lines in order to connect the java thread to the cpp thread
    env->GetJavaVM(&javavm);
    GetJniEnv(javavm, &envCamera);
    return 0;
}


bool GetJniEnv(JavaVM *vm, JNIEnv **env) {
    bool did_attach_thread = false;

    *env = nullptr;
    // Check if the current thread is attached to the VM
    auto get_env_result = vm->GetEnv((void**)env, JNI_VERSION_1_6);
    if (get_env_result == JNI_EDETACHED) {
        if (vm->AttachCurrentThread(env, NULL) == JNI_OK) {
            did_attach_thread = true;
        } else {
            // Failed to attach thread. Throw an exception if you want to.
        }
    } else if (get_env_result == JNI_EVERSION) {
        // Unsupported JNI version. Throw an exception if you want to.
    }
    return did_attach_thread;
}

以及我正在嘗試調用的 myCpp.cpp 線程中:

if (envMyClass != nullptr && classMyClass != nullptr && javavm != nullptr) {
    LOGD("000");
    jmethodID javaMethod = envMyClass->GetStaticMethodID(classMyClass, "myJavaFunction", "()V");
    LOGD("001");
    envMyClass->CallStaticVoidMethod(classMyClass, javaMethod);

}

它在“jmethodId javaMethod ..”行崩潰

myJavaFunction 是 MyJava class 中的一個方法:

public static void myJavaFunction() {
    Log.d("my_log", "jni callback");
}

碰撞:

   Abort message: 'JNI DETECTED ERROR IN APPLICATION: a thread (tid 12346 is making JNI calls without being attached
    in call to GetStaticMethodID'

知道如何解決嗎?

我注意到幾件事:

  1. 在 setListener 中,我假設您將jclass thiz分配給全局變量classMyClass 為此,您應該使用classMyClass = env->NewGlobalRef(thiz) ,否則 class 引用將無效( 參考)。
  2. 您正在調用GetJniEnv但您沒有檢查其結果,因此您實際上不知道當前線程是否已成功附加。
  3. 我假設您在setListener中附加當前線程,將 env 保存到全局變量,然后在代碼中的另一點使用該變量。 可能是您在兩者之間切換線程上下文嗎? 您可以執行以下操作以確保當前線程確實已附加:
    JNIEnv *thisEnv;
    int getEnvStat = jvm->GetEnv((void **)&thisEnv, JNI_VERSION_1_6 /* or whatever your JNI version is*/);
    if (getEnvStat == JNI_EDETACHED)
    {
        if (jvm->AttachCurrentThread(&thisEnv, NULL) != 0)
        {
           // throw error
        }
        else
        {
           jmethodID javaMethod = thisEnv->GetStaticMethodID(classMyClass, "myJavaFunction", "()V");
           thisEnv->CallStaticVoidMethod(classMyClass, javaMethod);
        }
    }
    else if (getEnvStat == JNI_OK)
    {
       jmethodID javaMethod = thisEnv->GetStaticMethodID(classMyClass, "myJavaFunction", "()V");
       thisEnv->CallStaticVoidMethod(classMyClass, javaMethod);
    }
    else if (getEnvStat == JNI_EVERSION)
    {
       // throw error
    }
}
  1. 如果調用jmethodID javaMethod = thisEnv->GetStaticMethodID(classMyClass, "myJavaFunction", "()V");可以使它更有效最初僅一次並將 jmethodID 存儲在全局變量中。 jmethodID 跨環境有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM