Jni本地多线程回调Java函数,env->findClass()失败。
来源:互联网 发布:网络小周迅BT 编辑:程序博客网 时间:2024/06/05 11:39
遇到的问题,Native层本地多线程回调Java函数时env->findClass()失败。
前面的代码是这样的在 JNI_OnLoad记录全局变量g_vm static JavaVM* g_vm = NULL;
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv * env = NULL;
if(g_vm == NULL){g_vm = vm;}
if( g_vm->GetEnv((void**)&env,JNI_VERSION_1_4) != JNI_OK ){
ALOGD("connot get g_Env is OK ");
return JNI_ERR;
}
return JNI_VERSION_1_4;
}
在子线程回调函数中去g_vm->AttachCurrentThread获取env,通过env去findClass代码如下这里发现cls == NULL
int nativeCallBackJava(int id)
{
jint result;
JNIEnv * env = NULL;
if(g_vm == NULL){return FALSE;}
result = (g_vm)->AttachCurrentThread(&env, NULL);
if(result != JNI_OK) {return FALSE;}
cls = (env)->FindClass("com/lipeng/NativeCallJava");
if(cls == NULL) {return FALSE;}
mid = (env)->GetStaticMethodID( cls, "nativeNotifyJava","(I)I");
if(mid == NULL) {return FALSE;}
(env)->CallStaticIntMethod( cls, mid, id);
return TRUE;
}
为什么会这样呢?我并没有看源码,觉得子线程AttachCurrentThread得到的env其类的加载器中并没有去加载自定义的类,所有这里你无法去findClass你自己的类,有人说这里find 系统类env->FindClass("java/lang/String");这样是可以的,我没有做尝试。
解决方案如下,
Java
1. 需要的类里面有个public native void setClsRef(void);
2. 在初始的时候调用本地函数来设计该类的全局引用
本地Native定义全局引用static jobject g_ObjCall= NULL;
实现setClsRef函数
3. JNIEXPORT void JNICALL Java_com_lipeng_NativeCallJava_setClsRef(JNIEnv* env, jobject thiz)
{
if(g_ObjCall == NULL){
g_ObjCall = env->NewGlobalRef(thiz);//获取全局引用
if(g_ObjCall == NULL)
{
ALOGD("get g_ObjCall == NULL) ");
}
if(thiz != NULL){
env->DeleteLocalRef(thiz);}//释放局部对象.这里可不要,调用结束后虚拟机会释放
}
4. 调用
int nativeCallBackJava(int id)
{
jint result;
JNIEnv * env = NULL;
if(g_vm == NULL){return FALSE;}
result = (g_vm)->AttachCurrentThread(&env, NULL);
if(result != JNI_OK) {return FALSE;}
cls = (env)->GetObjectClass(g_ObjAd);//从全局引用获取局部对象
if(cls == NULL) {return FALSE;}
mid = (env)->GetStaticMethodID( cls, "nativeNotifyJava","(I)I");
if(mid == NULL) {return FALSE;}
(env)->CallStaticIntMethod( cls, mid, id);
env->DeleteLocalRef(cls);//调用完后释放局部对象,这里是需要的,子线程调用该局部对象不会被虚拟机销毁,需显示调用Delete
return TRUE;
}
这样就可以在本地多线程随意使用了,回调Java层了,子线程结束后别忘了g_vm->DetachCurrentThread()
- Jni本地多线程回调Java函数,env->findClass()失败。
- android C++ 和 jni,根据JNIEnv的FindClass获取java类,包括多线程
- JNI 子线程FindClass
- JNI异步条件下(多线程/回调函数),如何取得JNI Env
- android JNI 多线程 C函数回调
- jni c本地代码回调java (多线程中,创建java对象时报空指针)未解决
- JNI 使用多线程回调java 方法
- Android JNI里c++调用java时遇到的FindClass返回0的问题
- jni实现回调java函数
- 《Java 本地接口规范》- JNI 函数(一)
- 《Java 本地接口规范》- JNI 函数(二)
- 《Java 本地接口规范》- JNI 函数(三)
- java本地方法通过jni连接至c函数
- Android使用NDK(从java调用本地函数'JNI')
- Android: JNI本地函数控制Java端代码
- JNI(Java Native Interface)多线程回调方法
- JNI FindClass Error in Native Thread
- Dalvik虚拟机的FindClass函数
- 10个基于浏览器的JavaScript调试工具分享
- 基于递归全排算法的最笨方式实现24点游戏
- 第三章 Data语义学
- POJ2362 Square
- 国际包裹到国内状态查询
- Jni本地多线程回调Java函数,env->findClass()失败。
- 人脸识别必读的N篇文章
- UVa 1588 Kickdown
- 《网络编程》带外数据
- Android 按两次返回键退出应用
- 用HtmlCleaner抓取新闻
- EditPlus配置c++运行环境
- XPath详解及Java示例代码
- Linux 配置收集 - Some Configuration In Linux - By黑月君