c与c++的JNIEnv不同
c,指针变量
typedef const struct JNINativeInterface* JNIEnv;
使用的时候 (*pEnv)->GetObjectClass(pEnv,obj);
c++,直接指向结构体
struct _JNIEnv;
struct _JavaVM;
typedef const struct JNINativeInterface* C_JNIEnv;
#if defined(__cplusplus)
typedef _JNIEnv JNIEnv;
typedef _JavaVM JavaVM;
使用的时候pEnv->GetObjectClass(obj);
不同线程间的JNIEnv不同,换句话说,就是在线程A中的JNIEnv,在线程B中不能使用。
JavaVM一个进程只有一个,java代码调用c++代码的时候jni给了一个JNIEnv变量,但是如果在c++中新创建了一个子线程C用于处理任务,那么在子线程C中不能使用前面的那个JNIEnv。如果子线程中想要使用JNIEnv,只能通过JavaVM得到一个新的JNIEnv,在子线程中使用。
一、获取JavaVM
1、通过JNIEnv获取JavaVM
JNIEXPORT jstring JNICALL Java_com_don_ndk_NDKTest_getHello
(JNIEnv *pEnv, jobject obj, jint param) {
pEnv->GetJavaVM(&javaVM);
jstring result = pEnv->NewStringUTF(getHello());
return result;
}
2、实现JNI_OnLoad方法,获取JavaVM
在加载动态链接库的时候,JVM会调用JNI_OnLoad(JavaVM* jvm, void* reserved)(如果定义了该函数),第一个参数会传入JavaVM指针。
JavaVM *javaVM = NULL;
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
javaVM = vm;
LOGI("JNI_OnLoad ndk test");
return JNI_VERSION_1_4;
}
二、通过JavaVM获取JNIEnv
创建子线程执行方法doThreadThing,通过calljstringMethod调用java代码
void threadTest() {
pthread_create(&pthread, NULL, doThreadThing, NULL);
}
void *doThreadThing(void *data) {
LOGI("doThreadThing ****************");
if (javaVM == NULL) {
LOGW("doThreadThing invalid javaVM");
return NULL;
}
JNIEnv *jniEnv = NULL;
jint ret = javaVM->GetEnv((void **) &jniEnv, JNI_VERSION_1_4);
LOGI("doThreadThing ret: %d", ret);
if (ret == JNI_EDETACHED) {
if (javaVM->AttachCurrentThread(&jniEnv, NULL) != JNI_OK) {
LOGW("doThreadThing AttachCurrentThread failed");
return NULL;
} else {
LOGI("doThreadThing AttachCurrentThread success");
}
}
if (jniEnv == NULL) {
LOGW("doThreadThing invalid jniEnv");
return NULL;
} else {
LOGI("doThreadThing get JNIEnv success");
}
calljstringMethod(jniEnv, jniObj);
javaVM->DetachCurrentThread();
pthread_exit(&pthread);
}
jniObj是在 Java_com_don_ndk_NDKTest_getHello 方法中保存的jobject变量
pthread_t pthread;
JavaVM *javaVM = NULL;
jobject jniObj = NULL;
JNIEXPORT jstring JNICALL Java_com_don_ndk_NDKTest_getHello
(JNIEnv *pEnv, jobject obj, jint param) {
jstring result = pEnv->NewStringUTF(getHello());
pEnv->GetJavaVM(&javaVM);
jniObj = pEnv->NewGlobalRef(obj);
threadTest();
return result;






网友评论