我有一个Android / Java应用程序,它通过JNI调用C ++代码来启动阻塞操作。 C ++代码启动一个线程来执行这个阻塞操作,然后它应该在JNI完成时回调。
调用C ++没有任何问题。但是,当回调JNI时,会报告错误的混合。
从新主题获取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");
}
不幸的是,由于某些未知的原因,这是记录/投掷:
Exception Ljava/lang/NoSuchMethodError; thrown while initializing Lcom/sample/SampleClazz;
NULL HERE
在处理不同的解决方案时,我尝试将GetMethodId
移动到JNI_OnLoad
方法,以便查看是否可以从原始Java线程中正确提取方法引用。它运行正常...但奇怪的是,一旦我这样做 回调中的代码也开始工作 。
我非常难过。我不知道发生了什么,不知道下一步该尝试什么。
答案 0 :(得分:0)
到目前为止,我已将其归结为在其他地方被抛出的错误,这是这种问题的症状。我创建了这些方法集,现在每次调用后都使用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崩溃了它就会让它自己保持下去,而不管怎么说就会破坏它。
答案 1 :(得分:0)
我知道这是很久以前的事了但是,我遇到了同样的问题。我发现我的Java类没有在任何Java代码中使用,因此它正在被优化。我在我的应用程序中使用了Java类,它现在都可以在C方面工作。