Jni本地多线程回调Java函数,env->findClass()失败。
遇到的问题,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()失败。的更多相关文章
- JNI通过线程c回调java层的函数
1.参看博客:http://www.jianshu.com/p/e576c7e1c403 Android JNI 篇 - JNI回调的三种方法(精华篇) 2.参看博客: JNI层线程回调Java函数关 ...
- javap 可以打印出用于jni调用的java函数的签名信息
javap可以打印出java的字节码: -c Prints out disassembled code, i.e., the instructions that comprise the Ja ...
- jni不通过线程c回调java的函数
整个工程的项目如下: 1.项目的思路是在activity中启动MyService这个服务,在服务中调用 JniScsManger类中的本地方法startNativeScsService,在 start ...
- jni不通过线程c回调java的函数 --总结
1.JNIEnv类型是一个指向全部JNI方法的指针.该指针只在创建它的线程有效,不能跨线程传递 2.JavaVM是虚拟机在JNI中的表示,一个JVM中只有一个JavaVM对象,这个对象是线程共享的. ...
- Android jni中回调java的方法
在上一篇的基础上,添加在C++代码中回调java方法. 代码如下: Demo.java 中添加callback函数, 打印一条log. package com.example.scarecrow.dy ...
- Android JNI编程(八)——体验AS2.2.2编写Jni程序、Java调C、C调Java函数、将C代码中的Log打印至Logcat
版权声明:本文出自阿钟的博客,转载请注明出处:http://blog.csdn.net/a_zhon/. 目录(?)[+] 不得不说在AS2.2以上的版本进行开发就一个字——爽,在2.0上使用jni出 ...
- Jni层回调java代码【转】
本文转载自:http://www.linuxidc.com/Linux/2014-03/97562.htm JNI是Java Native Interface的缩写,是Java平台的重要特性,使得Ja ...
- Android jni c/c++线程通过CallVoidMethod调用java函数出现奔溃问题
最近在移植网络摄像机里的p2p库到android平台,需要用到jni,最近在c线程了调用java函数的时候 出现一个问题,假如在同一个线程调用java函数是没问题的,但在一个c线程了调用java函数就 ...
- Python 3.X 调用多线程C模块,并在C模块中回调python函数的示例
由于最近在做一个C++面向Python的API封装项目,因此需要用到C扩展Python的相关知识.在此进行简要的总结. 此篇示例分为三部分.第一部分展示了如何用C在Windows中进行多线程编程:第二 ...
随机推荐
- 趣味js【练习题】
1.无限极函数递归,使每次的参数相乘 需求:add(1)(2)(3)(4)(5) 1.1首先要知道一个东西,就是function每次调用,都会默认执行tosting 1.2利用递归,每次返回的都是函数 ...
- AciveX接口事件的手动实现
为了理解ActiveX事件的运作原理,特意做了如下实验 初试化过程: try { CLSID clsid; HRESULT hr=::CLSIDFromProgID(L"MSWinsock. ...
- js中箭头函数和普通函数this的区别
最近在学习angularJs的时候由于里面涉及到了箭头函数,箭头函数除了声明上有点区别以外,和普通函数最主要的区别还是在this的问题上. Js中函数中嵌套的函数this不会 “继承”.比如说以下代码 ...
- Mutex 的正确打开方式
在使用 Mutex 在给线程/进程间加锁时,需要注意的问题. 1 AbandonedMutexException 在使用 mutex.WaitOne 时,可能抛出异常 AbandonedMutexEx ...
- 实验吧--隐写术--九连环--WriteUp
题目: http://ctf5.shiyanbar.com/stega/huan/123456cry.jpg 是一张图: 放到binwalk查看一下 发现存在压缩文件. 使用-e参数将文件分离 打开文 ...
- FastReport.Net使用:[8]交叉表一
1.绘制报表标题,交叉表可以直接放在标题栏内. 2.拖动一交叉表控件到标题栏内. 3.设置交叉表的行列信息. 将Tabel中的[科室名称]列拖到交叉表的列上以创建列,将Tabel中的[姓名]列拖到交叉 ...
- android 捕获所有异常 未捕获的异常
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 定义一个类 继承 应用, 实现 未捕获异常处理器 uncaughtExceptionHa ...
- 2018/3/13 noiρ[rəʊ]模拟赛 125分
T1 60分暴力,水分也不会水,打表也不会打,正解是不可能写正解的,这辈子都写不出来正解的,虽然是zz题但是也拿不到分这样子. 正解:(啥?正解是sb组合数?这都他娘的想不到,真鸡儿丢人我自杀吧.) ...
- AGC026D Histogram Coloring
link 题意: 给定n列的方块,第i列高度$h_i$.现在要把它染成红蓝两色,要求满足:对于任意一个$2\times 2$的区域,恰有2个蓝色,2个红色.问方案数. $n\leq 100,h_i\l ...
- Service里面启动Activity和Alertdialog
启动Activity源码:(记得要加上Intent.FLAG_ACTIVITY_NEW_TASK) Intent intent = new Intent(); intent.setFlags(Inte ...