JNI错误解决ERROR detaching thread with interp frames

写JNI在C++中回调Java中的函数,一般过程如下:

1. 先获取到JNIEnv*

获取方法:

 static JNIEnv* getJNIEnv(JavaVM* pJavaVM)
    {
    	JavaVMAttachArgs lJavaVMAttachArgs;
    	lJavaVMAttachArgs.version = JNI_VERSION_1_6;
    	lJavaVMAttachArgs.name = "NativeCallBack";
    	lJavaVMAttachArgs.group = NULL;
    	JNIEnv* lEnv;
    	if((pJavaVM)->AttachCurrentThread(&lEnv, &lJavaVMAttachArgs) != JNI_OK){
    		lEnv = NULL;
    	}
    	return lEnv;
    }

这里面需要调用AttachCurrentThread,来获取到Java函数的运行环境。

2. 通过JNI函数调用Java的函数

3. 最后调用DetachCurrentThread来释放getJNIEnv中获取的运行运行环境


然而,如果C++代码执行的回调实际是Java的线程,那么AttachCurrentThread函数虽然会执行成功(没有重新Attach),但是,在调用DetachCurrentThread会导致当前Java线程执行环境被Detach,导致:ERROR detaching thread with interp frames的错误。

所以,需要在getJNIEnv之前,先用

jint        (*GetEnv)(JavaVM*, void**, jint);

函数尝试获取JNIEnv,如果获取成功,说明当前执行的线程是Java线程。否则就是C++线程,需要调用getJNIEnv来获取Java环境。

比较完善的回调过程如下:

extern "C"
void callJavaMethod(int param){
        JavaVM* jvm = NULL;
        int status = env->GetJavaVM(&jvm);
	if(status!=0 || jvm == NULL) {
	        LOGI("GetJavaVM init fail");
		return;
	}
	JNIEnv* env = NULL;
	bool needDetach = false;
	if (jvm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK) {
		env = getJNIEnv(jvm);
		needDetach = true;
		LOGI("got Env by attach Thread");
	}

	if (env == NULL)
	{
		LOGI("getJNIEnv failed");
		return;
	}
	//Call java Method 
	LOGI("callback success");
	if(needDetach){
		jvm->DetachCurrentThread();
	}
}


参考资料:

1 http://stackoverflow.com/questions/13028247/android-spotify-error-detaching-thread-with-interp-frames-count-28


你可能感兴趣的:(JNI错误解决ERROR detaching thread with interp frames)