![](/img/trans.png)
[英]Fatal Exception: java.lang.NoClassDefFoundError when calling static method in Android app
[英]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'
知道如何解決嗎?
我注意到幾件事:
jclass thiz
分配給全局變量classMyClass
。 為此,您應該使用classMyClass = env->NewGlobalRef(thiz)
,否則 class 引用將無效( 參考)。GetJniEnv
但您沒有檢查其結果,因此您實際上不知道當前線程是否已成功附加。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
}
}
jmethodID javaMethod = thisEnv->GetStaticMethodID(classMyClass, "myJavaFunction", "()V");
可以使它更有效最初僅一次並將 jmethodID 存儲在全局變量中。 jmethodID 跨環境有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.