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. 悟透JavaScript

    要理解JavaScript,你得首先放下对象和类的概念,回到数据和代码的本原.前面说过,编程世界只有数据和代码两种基本元素,而这两种元素又有着纠缠不清的关系.JavaScript就是把数据和代码都简化 ...

  2. 在 Ubuntu 上安装 Android Studio

    在 Ubuntu 上安装 Android Studio http://www.linuxidc.com/Linux/2013-05/84812.htm 打开terminal,输入以下命令 sudo a ...

  3. ActiveX(一)第一个简单的Demo

    说道ActiveX,我的第一直觉就是Flash,利用ActiveX.我们可以创建丰富的可交互式应用程序.同时.利用ActiveX特性.我们可以实现Js 与 ActiveX 的无缝连接(包括数据共享.和 ...

  4. [Asp.net 5] Localization-resx资源文件的管理

    上一篇博文地址:[Asp.net 5] Localization-简单易用的本地化-全球化信息 本文继续介绍asp.net 5多语言.今天重点讲的是多语言的resx文件.涉及到的工程有:Microso ...

  5. Oracle学习总结_day05_集合_连接查询

    本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! day05_集合_连接查询 集合操作符 UNION ( ...

  6. c语言 sizeof理解

    1.基本数据类型 char :1     short:2   int 4    long 4   long long :8    float:4    double :8字节. 2.数组:对应的基本数 ...

  7. php实现设计模式之 适配器模式

    <?php /* * 适配器模式:将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原来由于接口不兼容而不能一起工作的那些类可以一起工作(结构型模式) * * 一个源接口,不符合 ...

  8. Javascript:JSON总结

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它是基于ECMAScript的一个子集,采用完全独立于语言的文本格式.这些特性使JSON成为理想的数据交换 ...

  9. Javascript 创建对象方法的总结

    最近看了一下<Javascript高级程序设计(第三版)>,这本书很多人都推荐,我也再次郑重推荐一下.看过之后总得总结一下吧,于是我选了这么一个主题分享给大家. 使用Javascript创 ...

  10. 未能加载包“Microsoft SQL Server Data Tools”

    直接在vs2013里的App_Data目录创建数据库,在服务器资源管理器中查看时报错: 未能加载包“Microsoft SQL Server Data Tools” 英文: The 'Microsof ...