美文网首页
JNI多线程中findclass找不到自定义类

JNI多线程中findclass找不到自定义类

作者: 椰子 | 来源:发表于2020-08-23 21:20 被阅读0次

问题:

我要用ndk编译c++的代码,其中包含了多线程,主线程和回调线程。
在主线程中使用env->GetJavaVM(&g_jvm);得到了全局的vm,
在回调线程中我首先得到了env:
JNIEnv* env = NULL;
g_jvm->AttachCurrentThread(&env, NULL);
然后利用
jclass cls = env->FindClass("vc/db/DataSearchService");
(其中vc/db是包名,DataSearchService是自定义的类名)
在主线程中调用 env->FindClass("vc/db/DataSearchService");是没有问题的

解决方案:

1.在主线程调用 jclass cls = env->FindClass("vc/db/DataSearchService"); 然后用NewGlobalRef为这个cls申请全局引用,否则这只是个局部引用,跨线程仍然挂。

<结构体>
typedef struct java_callback {
    int code;
    jobject obj;
    jobject cls;//回调需要的java bean
    void *response;
} java_callback;

java_callback javaCallback;
<主线程调用>
JNIEXPORT void JNICALL
Java_com_xxx_xxx_testCallback(JNIEnv *env, jobject thiz, jobject query_order_listener) {
    javaCallback.obj = (env)->NewGlobalRef(query_order_listener);
    jclass cls= env->FindClass("com/xxx/xxx/QueryOrderBean");
    javaCallback.cls = env->NewGlobalRef(cls);
}


<子线程中调用:>
/**
 * 在此处跑在子线程中,并回调到java层
 */
void *callbackThreadHandler(void *p) {
    if (p == NULL) {
        logE("callbackThreadHandler>>>p is NULL");
        pthread_exit(&callbackThread);
      }
    JNIEnv *env;
//获取当前native线程是否有没有被附加到jvm环境中
    int getEnvStat = g_VM->GetEnv((void **) &env, JNI_VERSION_1_6);
    if (getEnvStat == JNI_EDETACHED) {
        //如果没有,主动附加到jvm环境中,获取到env
        if (g_VM->AttachCurrentThread(&env, NULL) != 0) {
            pthread_exit(&callbackThread);
        }
    }
    //强转回来
    auto jcallback = (java_callback *) p;
//通过强转后的jcallback 获取到要回调的类
   jclass javaClass = env->GetObjectClass(jcallback->obj);
   if (javaClass == 0) {
        logE("Unable to find class");
        g_VM->DetachCurrentThread();
        pthread_exit(&callbackThread);
     }
//获取要回调的方法ID 参数1:类名, 参数2:方法名, 参数3:方法名的签名
   jmethodID javaCallbackId = env->GetMethodID(javaClass, "onQueryOrder",
                                     "(Lcom/xxx/xxx/QueryOrderBean;)V"); 
   if (javaCallbackId == NULL) {
        logE("Unable to find method: onFaceDetect");
        pthread_exit(&callbackThread);
    }
//找到对象的Java类
   auto queryOrderClass = (jclass) jcallback->cls;
// 获取类的构造函数,记住这里是调用无参的构造函数
   jmethodID id = env->GetMethodID(queryOrderClass, "<init>", "()V");
// 创建一个新的对象
   jobject queryOrderBean = env->NewObject(queryOrderClass, id);
//对应的java属性
   jfieldID time = env->GetFieldID(queryOrderClass, "time", "Ljava/lang/String;");
//属性赋值,queryOrderBean
   env->SetObjectField(queryOrderBean, time, env->NewStringUTF(response2021->time));
//执行回调
   env->CallVoidMethod(jcallback->obj, javaCallbackId, queryOrderBean);
   env->DeleteLocalRef(queryOrderBean);
}
class QueryOrderBean {
    val time: String = "" 
}

相关文章

网友评论

      本文标题:JNI多线程中findclass找不到自定义类

      本文链接:https://www.haomeiwen.com/subject/bhuwjktx.html