問題:
我要用ndk編譯c++的代碼寻定,其中包含了多線程呛牲,主線程和回調(diào)線程备绽。
在主線程中使用env->GetJavaVM(&g_jvm);得到了全局的vm议泵,
在回調(diào)線程中我首先得到了env:
JNIEnv* env = NULL;
g_jvm->AttachCurrentThread(&env, NULL);
然后利用
jclass cls = env->FindClass("vc/db/DataSearchService");
(其中vc/db是包名占贫,DataSearchService是自定義的類名)
在主線程中調(diào)用 env->FindClass("vc/db/DataSearchService");是沒有問題的
解決方案:
1.在主線程調(diào)用 jclass cls = env->FindClass("vc/db/DataSearchService"); 然后用NewGlobalRef
為這個cls申請全局引用,否則這只是個局部引用先口,跨線程仍然掛型奥。
<結(jié)構(gòu)體>
typedef struct java_callback {
int code;
jobject obj;
jobject cls;//回調(diào)需要的java bean
void *response;
} java_callback;
java_callback javaCallback;
<主線程調(diào)用>
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);
}
<子線程中調(diào)用:>
/**
* 在此處跑在子線程中,并回調(diào)到j(luò)ava層
*/
void *callbackThreadHandler(void *p) {
if (p == NULL) {
logE("callbackThreadHandler>>>p is NULL");
pthread_exit(&callbackThread);
}
JNIEnv *env;
//獲取當(dāng)前native線程是否有沒有被附加到j(luò)vm環(huán)境中
int getEnvStat = g_VM->GetEnv((void **) &env, JNI_VERSION_1_6);
if (getEnvStat == JNI_EDETACHED) {
//如果沒有碉京,主動附加到j(luò)vm環(huán)境中厢汹,獲取到env
if (g_VM->AttachCurrentThread(&env, NULL) != 0) {
pthread_exit(&callbackThread);
}
}
//強轉(zhuǎn)回來
auto jcallback = (java_callback *) p;
//通過強轉(zhuǎn)后的jcallback 獲取到要回調(diào)的類
jclass javaClass = env->GetObjectClass(jcallback->obj);
if (javaClass == 0) {
logE("Unable to find class");
g_VM->DetachCurrentThread();
pthread_exit(&callbackThread);
}
//獲取要回調(diào)的方法ID 參數(shù)1:類名, 參數(shù)2:方法名, 參數(shù)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;
// 獲取類的構(gòu)造函數(shù),記住這里是調(diào)用無參的構(gòu)造函數(shù)
jmethodID id = env->GetMethodID(queryOrderClass, "<init>", "()V");
// 創(chuàng)建一個新的對象
jobject queryOrderBean = env->NewObject(queryOrderClass, id);
//對應(yīng)的java屬性
jfieldID time = env->GetFieldID(queryOrderClass, "time", "Ljava/lang/String;");
//屬性賦值谐宙,queryOrderBean
env->SetObjectField(queryOrderBean, time, env->NewStringUTF(response2021->time));
//執(zhí)行回調(diào)
env->CallVoidMethod(jcallback->obj, javaCallbackId, queryOrderBean);
env->DeleteLocalRef(queryOrderBean);
}
class QueryOrderBean {
val time: String = ""
}