遇到的问题,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()失败。的更多相关文章

  1. JNI通过线程c回调java层的函数

    1.参看博客:http://www.jianshu.com/p/e576c7e1c403 Android JNI 篇 - JNI回调的三种方法(精华篇) 2.参看博客: JNI层线程回调Java函数关 ...

  2. javap 可以打印出用于jni调用的java函数的签名信息

    javap可以打印出java的字节码: -c     Prints out disassembled code, i.e., the instructions that comprise the Ja ...

  3. jni不通过线程c回调java的函数

    整个工程的项目如下: 1.项目的思路是在activity中启动MyService这个服务,在服务中调用 JniScsManger类中的本地方法startNativeScsService,在 start ...

  4. jni不通过线程c回调java的函数 --总结

    1.JNIEnv类型是一个指向全部JNI方法的指针.该指针只在创建它的线程有效,不能跨线程传递 2.JavaVM是虚拟机在JNI中的表示,一个JVM中只有一个JavaVM对象,这个对象是线程共享的. ...

  5. Android jni中回调java的方法

    在上一篇的基础上,添加在C++代码中回调java方法. 代码如下: Demo.java 中添加callback函数, 打印一条log. package com.example.scarecrow.dy ...

  6. Android JNI编程(八)——体验AS2.2.2编写Jni程序、Java调C、C调Java函数、将C代码中的Log打印至Logcat

    版权声明:本文出自阿钟的博客,转载请注明出处:http://blog.csdn.net/a_zhon/. 目录(?)[+] 不得不说在AS2.2以上的版本进行开发就一个字——爽,在2.0上使用jni出 ...

  7. Jni层回调java代码【转】

    本文转载自:http://www.linuxidc.com/Linux/2014-03/97562.htm JNI是Java Native Interface的缩写,是Java平台的重要特性,使得Ja ...

  8. Android jni c/c++线程通过CallVoidMethod调用java函数出现奔溃问题

    最近在移植网络摄像机里的p2p库到android平台,需要用到jni,最近在c线程了调用java函数的时候 出现一个问题,假如在同一个线程调用java函数是没问题的,但在一个c线程了调用java函数就 ...

  9. Python 3.X 调用多线程C模块,并在C模块中回调python函数的示例

    由于最近在做一个C++面向Python的API封装项目,因此需要用到C扩展Python的相关知识.在此进行简要的总结. 此篇示例分为三部分.第一部分展示了如何用C在Windows中进行多线程编程:第二 ...

随机推荐

  1. 在LoadRunner中从数组类型的参数随机取值的方法

    在LoadRunner中从数组类型的参数随机取值的方法 使用web_reg_save_param做关联后,有时候会有多个匹配值. 为了模仿用户行为随机取一个值为后续transcation所用,可以使用 ...

  2. logstash收集rsyslog日志

    (1)rsyslog配置 在192.168.1.31配置 #vim /etc/rsyslog.conf *.* @@192.168.1.32:514 //所有设备名,所有日志级别都发送到192.168 ...

  3. 【C#】IEnumrator的枚举数和IEnumerable接口

    声明IEnumerator的枚举数 要创建非泛型接口的枚举数,必须声明实现IEnumerator接口的类,IEnumerator接口有如下特性: 1.她是System.Collections命名空间的 ...

  4. elementUI 学习入门之 layout 布局

    layout 布局 通过基础的 24 分栏,可进行快速布局 基础布局 使用单一分栏创建基础的栅格布局, 通过 span 属性指定每栏的大小 <el-col :span="8" ...

  5. 【转】使用 python IDLE 自带的 debuger 进行调试

    IDLE自带了调试器(虽然不怎么使吧). 关于如何在 IDLE 中进行调试网上的教程讲的很模糊,于是自己整理了一下,和大家分享~ 第一步:打开python shell,并在shell中打开debuge ...

  6. [Codeforces19D]Points 线段树

    大致题意: 给出n个询问,每次询问有三种: 1.往平面上加一个点 2.删除平面上的一个点 3.给出一个点p,查询平面上某点q,使得q.x>p.x且q.y>p.y,输出x轴坐标最小的q,若有 ...

  7. zimg 启动命令

    cd zimgcd bin ./zimg conf/zimg.lua

  8. 分布式锁的理解,java自带的锁为什么会失效

    前段时间在发送短信的代码块上通过网上找的工具类基于Redis实现了分布式锁的功能 对应的链接https://www.cnblogs.com/c-h-y/p/9391602.html 周末想细细看一下. ...

  9. Boolean Expressions POJ - 2106 (表达式求值)

    The objective of the program you are going to produce is to evaluate boolean expressions as the one ...

  10. 【BZOJ 4229】 4229: 选择 (线段树+树链剖分)

    4229: 选择 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 67  Solved: 41 Description 现在,我想知道自己是否还有选择. ...