从pthread初始化对象时出现“NoSuchMethodError” 我有一个Android /java应用程序,通过JNI调用C++代码,开始一个阻塞操作。C++代码启动线程来执行这个阻塞操作,然后在完成时通过JNI调用。 调用C++没有任何问题。然而,当调用JNI时,会报告多种错误

从pthread初始化对象时出现“NoSuchMethodError” 我有一个Android /java应用程序,通过JNI调用C++代码,开始一个阻塞操作。C++代码启动线程来执行这个阻塞操作,然后在完成时通过JNI调用。 调用C++没有任何问题。然而,当调用JNI时,会报告多种错误,android,c++,android-ndk,java-native-interface,Android,C++,Android Ndk,Java Native Interface,从新线程获取jclass引用显然是不合法的。执行该操作会产生不可预测的行为,因此所有类查找都在JNI_OnLoad方法中执行,如下所示: static jclass sampleClazz; jint JNI_OnLoad(JavaVM *vm, void *reserved) { jvm = vm; JNIEnv* env = NULL; jint result = jvm->GetEnv((void**)&env, JNI_VERSION_1_6);

从新线程获取jclass引用显然是不合法的。执行该操作会产生不可预测的行为,因此所有类查找都在JNI_OnLoad方法中执行,如下所示:

static jclass sampleClazz;

jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
    jvm = vm;

    JNIEnv* env = NULL;
    jint result = jvm->GetEnv((void**)&env, JNI_VERSION_1_6);

    if(env == NULL) { __android_log_print(ANDROID_LOG_DEBUG, "JNI_OnLoad", "NULL");}

    sampleClazz= env->FindClass("com/sample/SampleClazz");
    sampleClazz= (jclass) env->NewGlobalRef(sampleClazz);

    ...etc...
}
在其中一个线程中,我试图调用Java代码。回调方法与此类似:

void cCallBackOne() {
    JNIEnv* env;
    jvm->AttachCurrentThreadAsDaemon(&env, NULL);

    jmethodID init = env->GetMethodID(sampleClazz, "<init>", "()V");
    if(init == NULL) { 
        __android_log_print(ANDROID_LOG_DEBUG, "START", "NULL HERE"); 
    } else {
        __android_log_print(ANDROID_LOG_DEBUG, "START", "ALL FINE"); 
    }
在处理不同的解决方案时,我尝试将GetMethodId移动到JNI_OnLoad方法,以查看是否能够正确地从原始Java线程中提取方法引用。它很好用。。。但奇怪的是,一旦我这样做了,回调中的代码也开始工作了


我被难住了。我不知道发生了什么,也不确定下一步要尝试什么。

到目前为止,我把它归因于在其他地方抛出的错误,这就是这样一个问题的症状。我已经创建了这些方法集,现在在每次调用后使用check:

void check(jclass toCheck) {
    if(toCheck == NULL) {
        __android_log_print(ANDROID_LOG_ERROR, "Check", "Error retrieving jclass");
    }
}

void check(jmethodID toCheck) {
    if(toCheck == NULL) {
        __android_log_print(ANDROID_LOG_ERROR, "Check", "Error retrieving jmethodID");
    }
}

void check(jfieldID toCheck) {
    if(toCheck == NULL) {
        __android_log_print(ANDROID_LOG_ERROR, "Check", "Error retrieving jfieldID");
    }
}

void check(jobject toCheck) {
    if(toCheck == NULL) {
        __android_log_print(ANDROID_LOG_ERROR, "Check", "Error retrieving jobject");
    }
}
只是加上这些支票就解决了我的问题。。。为了理智起见,我希望有一个原因,而不是魔法来解释为什么这是

虽然我不得不承认在代码执行的早期出现了一些奇怪的异常,但这只是早期崩溃的一个症状


教训:记住隔离你的代码人员!如果JNI崩溃了,它将保持它自己的状态,而路的另一端会发生故障。

到目前为止,我把它归因于在其他地方抛出的错误,这就是这样一个问题的症状。我已经创建了这些方法集,现在在每次调用后使用check:

void check(jclass toCheck) {
    if(toCheck == NULL) {
        __android_log_print(ANDROID_LOG_ERROR, "Check", "Error retrieving jclass");
    }
}

void check(jmethodID toCheck) {
    if(toCheck == NULL) {
        __android_log_print(ANDROID_LOG_ERROR, "Check", "Error retrieving jmethodID");
    }
}

void check(jfieldID toCheck) {
    if(toCheck == NULL) {
        __android_log_print(ANDROID_LOG_ERROR, "Check", "Error retrieving jfieldID");
    }
}

void check(jobject toCheck) {
    if(toCheck == NULL) {
        __android_log_print(ANDROID_LOG_ERROR, "Check", "Error retrieving jobject");
    }
}
只是加上这些支票就解决了我的问题。。。为了理智起见,我希望有一个原因,而不是魔法来解释为什么这是

虽然我不得不承认在代码执行的早期出现了一些奇怪的异常,但这只是早期崩溃的一个症状


教训:记住隔离你的代码人员!如果JNI撞车了,它会自动关闭,而路的另一端会发生故障。

我知道这是很久以前的事了,但我也遇到了同样的问题。我发现我的Java类没有在任何Java代码中使用,因此正在对其进行优化。我在我的应用程序中使用了Java类,现在一切都可以从C端工作。

我知道这是很久以前的事了,但我也遇到了同样的问题。我发现我的Java类没有在任何Java代码中使用,因此正在对其进行优化。我在我的应用程序中使用了Java类,现在所有这些都可以从C端工作。

不完全相关,但是如果你阻止,为什么要启动线程?听起来你可以在同一个线程中完成这项工作……你试过用Java创建线程吗?这就是我所做的阻塞操作,它们工作得很好。那么就没有必要去搞乱有问题的C到Java回调机制。我可以确认,我这样做是有充分理由的。这可能只是一个打字错误,但是回调中的sampleClazz不应该是JNI_OnLoad中定义的stringClazz吗?请注意JNI_OnLoad中的省略。为了清晰起见,现在将更改它。不完全相关,但如果您阻止,为什么要启动线程?听起来你可以在同一个线程中完成这项工作……你试过用Java创建线程吗?这就是我所做的阻塞操作,它们工作得很好。那么就没有必要去搞乱有问题的C到Java回调机制。我可以确认,我这样做是有充分理由的。这可能只是一个打字错误,但是回调中的sampleClazz不应该是JNI_OnLoad中定义的stringClazz吗?请注意JNI_OnLoad中的省略。为了清晰起见,现在将更改它。