JAVA JNI 中解决在C/C++跨线程FindClass失败
在JAVA与C/C++交互时使用JNI接口;
先是在JAVA调用的C++方法中直接测试FindClass,使用获取到的jclass操作没有任何问题;
但是在调用的C++方法中起线程后,在线程中FindClass有一定概率异常。
经过一天的时间,在网上查找资料并反复调试,终于解决了问题。
步骤如下:
① C++代码主线程中的操作:
///> 定义一个全局JavaVM *类型变量 Jvm,在主线程中获取JAVA虚拟机。
env->GetJavaVM(&Jvm);
///> 定义一个全局jobject类型变量 JObj,在主线程中保存JAVA传递过来的jobject。
JObj = env->NewGlobalRef(instance);
///> 定义一个局部变量保存FindClass的结果。
jclass tmpeClass = env->FindClass("com/myfile/Service/myclass");
///> 定义一个jclass 类型的全局变量JClass来保存FindClass结果的引用,保证在其他线程也能使用。
JClass = (jclass)env->NewGlobalRef(tmpeClass); ///> 注意!!!要把结果转换为jclass类型!
///> 然后就可以起线程了,起线程不在此赘述。
pthread_create(&myThread, NULL, thread_function, NULL);
② thread_function线程中的操作:
///> 将主线程中保存的Jvm中的JNIEnv取出来
JNIEnv *env;
Jvm->AttachCurrentThread((void **)&env, NULL);
///> 使用保存的全局JClass获取其中的属性ID
jfieldID ageFID = env->GetFieldID(JClass , "age", "B");
///> 使用此JClass申请对象。
jobject newObject = env->AllocObject(JClass);
///> 给该对象设置值。
env->SetByteField(newObject, ageFID , 30);
///> 获取JAVA提供的方法
jclass clazz = env->GetObjectClass(JObj);
jmethodID javaMID = env->GetMethodID(clazz, "CallMe", "(Lcom/myfile/Service/myclass;)V"); ///> 该方法的参数是FindClass的类
///> 最后就可调用JAVA提供的方法把赋好值的对象传递给JAVA。
env->CallVoidMethod( JObj, javaMID , newObject);