jni层调试线程死机原因

一,导致死机原因:

  jni层中  线程函数中  只要添加调用env 的函数 ,,就会死机  
 
二,解决方法
第一我们应该理解:
①(独立性) JNIEnv 是一个与线程相关的变量,即线程A有一个 JNIEnv变量, 线程B也有一个JNIEnv变量,由于线程相关,所以A线程不能使用B线程的 JNIEnv 结构体变量。那么如何保证了每个线程JNIEnv的独立性呢?
 

一个java对象通过JNI调用DLL中一个send()函数向服务器发送消息,不等服务器消息到来就立即返回,同时把JNI接口的指针JNIEnv *env(虚拟机环境指针),和jobject obj保存在DLL中的变量里.一段时间后,DLL中的消息接收线程接收到服务器发来的消息,并试图通过保存过的env和obj来调用先前的java对象的方法(相当于JAVA回调方法)来处理此消息此时程序会突然退出(崩溃).

即前台JAVA线程发送消息,后台线程处理消息,归属于两个不同的线程,不能使用相同的JNIEnv变量,这里可以利用一个机制: 利用全局的 JavaVM * 指针得到当前线程的 JNIEnv* 指针,与在C++中两个线程使用TLS进行局部存储类似的原理。

具体方法:

获取全局的JavaVM变量:

/* Our VM */
JavaVM *g_vm;

env->GetJavaVM(&g_vm); //来获取JavaVM指针.获取了这个指针后,将该JavaVM保存起来。(转录)

②(公共性) 先了解TLS(thread-local storage)

线程是执行的单元,同一个进程内的多个线程共享了进程的地址空间,线程一般有自己的栈,但是如果想要实现某个全局变量在不同的线程之间取不同的值,而且不受影响。一种办法是采用线程的同步机制,如对这个变量的读写之处加临界区或者互斥量,但是这是以牺牲效率为代价的,能不能不加锁呢?线程局部存储就是干这个的。


 解决以上两个问题:
1首先定义全局变量
namespace android
{
static JavaVM* gJavaVM = NULL; //定义一个全局Java VM引用对象
static jobject gJavaObj = NULL; //定义一个全局Java object对象,对于java层的类对象
    ......

2其次在调用某个线程的函数中定义:(保证线程在进程中资源的公共性,这两句是把参数传给所开线程)

JNIEXPORT void JNICALL Java_Test_setEnev(JNIEnv *env, jobject obj)  

{  

    env->GetJavaVM(&gs_jvm); //保存到全局变量中JVM   

    //直接赋值obj到DLL中的全局变量是不行的,应该调用以下函数:   

    gs_object=env->NewGlobalRef(obj);  

 HANDLE ht=CreateThread(NULL,,(LPTHREAD_START_ROUTINE)ThreadFun,,NULL,NULL);  

}
3在线程函数中 引用:  (保证线程函数 对应  env  和class)
void WINAPI ThreadFun(PVOID argv)//JNI中线程回调这个方法   

{   

 JNIEnv *env;  

 gs_jvm->AttachCurrentThread((void **)&env, NULL);    //对应这几句说白了就是从上面函数中把变量取出来在该线程中使用

 jclass cls = env->GetObjectClass(gs_object);   //获取JAVA线程中的全局对象

 jfieldID fieldPtr = env->GetFieldID(cls,"value","I");   // 获取JAVA对象

 while()  

 {  

    Sleep();  

   //这里改变JAVA对象的属性值(回调JAVA)   

   env->SetIntField(gs_object,fieldPtr,(jint)gs_i++);  

  }  

}

三,我们在网上看到有些关于jni的程序资料用了(*env)->;

我们需要谨记:在linux下如果.c文件中用 “env->” 编译会找不到此结构,必须用“(*env)->”,或者改成.cpp文件,以 c++的方式来编译。

------------------------------------------------------------------------
 
 
 
 

jni调试3(线程调试env变量问题)的更多相关文章

  1. 经典的GDB调试命令,包括查看变量,查看内存

    经典的GDB调试命令,包括查看变量,查看内存 在你调试程序时,当程序被停住时,你可以使用print命令(简写命令为p),或是同义命令inspect来查看当前程序的运行数据.print命令的格式是: p ...

  2. vs.net调试ArcGIS Engine代码查看变量时,提示“要检查本机对象,请启用本机代码调试。” 的解决方法

    用vs2017 调试 查看ArcGIS Engine 的变量时 会提示如下图所示的错误: 解决方法: 工具->选项->调试->常规->使用托管的兼容模式 如下图所示: 2.设置 ...

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

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

  4. 调试多线程 & 查死锁的bug & gcore命令 & gdb对多线程的调试 & gcore & pstack & 调试常用命令

    gdb thread apply all bt 如果你发现有那么几个栈停在 pthread_wait 或者类似调用上,大致就可以得出结论:就是它们几个儿女情长,耽误了整个进程. 注意gdb的版本要高于 ...

  5. Visual Studio 调试系列9 调试器提示和技巧

    系列目录     [已更新最新开发文章,点击查看详细] 01 固定数据提示 如果你在调试时,经常将鼠标悬停在数据提示上,就可能想固定变量的数据提示,方便自己随时查看. 即使在重新启动后,固定的变量也能 ...

  6. Jmeter 将正则表达式提取的参数传给全局(跨线程组使用变量)

    一.使用正则表达式提取sessionId 1.在测试计划(跨线程组使用变量)--> 线程组(登录)--> 添加HTTP请求(登录接口) (1)创建测试计划: 勾选独立运行每个线程组(例如在 ...

  7. .NET高级调试系列-Windbg调试入门篇

    Windbg是.NET高级调试领域中不可或缺的一个工具和利器,也是日常我们分析解决问题的必备.准备近期写2篇精华文章,集中给大家分享一下如果通过Windbg进行.NET高级调试. 今天我们来一篇入门的 ...

  8. Linux学习——Gdb基本调试方法&&多线程调试

    1.Gdb的基本调试 示例代码 //e.c #include <stdio.h> void debug(char *str) { printf("debug info :%s\n ...

  9. [Android Studio 权威教程]断点调试和高级调试

    好了开始写一个简单的调试程序,我们先来一个for循环 ? 1 2 3 4 5 6 7 8 <code class="language-java hljs ">for ( ...

随机推荐

  1. Struts2 源码分析——DefaultActionInvocation类的执行action

    本章简言 上一章讲到关于拦截器的机制的知识点,让我们对拦截器有了一定的认识.我们也清楚的知道在执行用户action类实例之前,struts2会先去执行当前action类对应的拦截器.而关于在哪里执行a ...

  2. 利用jquery.validate以及bootstrap的tooltip开发气泡式的表单校验组件

    表单校验是页面开发中非常常见的一类需求,相信每个前端开发人员都有这方面的经验.网上有很多成熟的表单校验框架,虽然按照它们默认的设计,用起来没有多大的问题,但是在实际工作中,表单校验有可能有比较复杂的个 ...

  3. WCF 框架运行时类图

    本文画出了 WCF 框架运行时的重点类之间的类关系图. Binding 一个 Binding 由多个 BindingElement 组成.BindingElement 作为主要的扩展点.每一个 Bin ...

  4. C#使用iTextSharp给PDF添加水印

    代码: /// <summary> /// 添加普通偏转角度文字水印 /// </summary> public static void SetWatermark(string ...

  5. Devexpress RaisePropertyChanged

    所有的重载设置字段作为参数传递到指定的值,而属性提高INotifyPropertyChanged.PropertyChanged事件. 如果一个字段已经成功地改变,setProperty方法中返回真. ...

  6. Visual Studio 2015在.NET Core RC2项目中的一个错误。

    更新了.NET Core RC2 之后,VS的Web Tools更新为“Preview 1”了. 这个版本有一个问题,害我折腾了一个下午. 就是在项目界面的“依赖项 - NPM”上面错误地显示了不必要 ...

  7. 把生成的excel文件直接提供为下载页效果

    把php中的excel显示下载页下载到本地硬盘需要设置头信息: 代码: $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Ex ...

  8. HotCode的原理及使用

    1. JRbel介绍 JRebel是一套JavaEE开发工具.Jrebel可快速实现热部署,节省了大量重启时间,提高了个人开发效率.网上可搜索到破解版.JRebel是一款JAVA虚拟机插件,它使得JA ...

  9. javascript 模式(1)——代码复用

    程序的开发离不开代码的复用,通过代码复用可以减少开发和维护成本,在谈及代码复用的时候,会首先想到继承性,但继承并不是解决代码复用的唯一方式,还有其他的复用模式比如对象组合.本节将会讲解多种继承模式以实 ...

  10. K 均值算法(K-means)

    K-means算法是最简单的一种聚类算法.算法的目的是使各个样本与所在类均值的误差平方和达到最小(这也是评价K-means算法最后聚类效果的评价标准) K-means聚类算法的一般步骤: 1. 初始化 ...