遇到的问题,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()

最新文章

  1. HDU 1082
  2. iOS 7中使用UINavigationController进行pop崩溃
  3. Java构造和解析Json数据的两种方法详解一
  4. 深入学习JS: __doPostBack函数
  5. BA - 读书雷达10本必读书
  6. Spring MVC 中的REST支持
  7. sublime快捷方式和node.js
  8. jq商品展示图放大镜 and 原生js和html5写的放大镜效果 ~~效果不错
  9. 自己动手写处理器之第一阶段(2)——MIPS指令集架构的演变
  10. 9.4、Libgdx简单字符输入
  11. bootstrap-editable实现bootstrap-table行内编辑
  12. java String[] 初始化
  13. nodejs server websocket
  14. python-爬虫-selenium模块
  15. python中range()、list()函数的用法
  16. 8分钟丨教你玩转 API
  17. Oracle EBS AR 删除应收发票
  18. 用 #include “filename.h” 格式来引用非标准库的头文件
  19. FPN(feature pyramid networks)
  20. Vim技能修炼教程(17) - 编译自己的Vim

热门文章

  1. 【PAT】1007. 素数对猜想 (20)
  2. day4装饰器
  3. loadrunner场景执行出现:Failed to Initialize. Reason: TimeOut
  4. 微软企业库5.0 学习之路——扩展学习篇、库中的依赖关系注入(重构 Microsoft Enterprise Library)[转]
  5. BOM知识整理
  6. 转:gcc编译C++程序
  7. Windows环境上装在VM,VM安装CentOS7
  8. 在ASP.NET中实现图片、视频文件上传方式
  9. 字符串的模板 Manacher kmp ac自动机 后缀数组 后缀自动机
  10. bzoj 3931: [CQOI2015]网络吞吐量 -- 最短路+网络流