• 假设你想了解JNI在怎样在多线程下使用
  • 假设你在子线程使用JNI时遇到findClass不能找到目标Class,而在主线程下却能找到该Class的问题。或是GetEnv返回NULL的问题
  • 假设你想多学点编程技术的话
那么,这篇文章就是为你而写的, :)

近期工作中遇到这么个问题:c++代码须要调用Android的API来做一个比較耗时的任务,由于有点耗时,希望能有个进度条显示给用户,非常自然地,我创建了一个子线程用来执行这个耗时的任务,依照平时写法,结果一执行,GetEnv获取失败了。网上查找一番,官方说明有这么句话:
If the current thread is not attached to the VM, sets *env to NULL,
and returns JNI_EDETACHED. If the specified
version is not supported, sets *env to NULL,
and returns JNI_EVERSION. Otherwise,
sets *env to the appropriate interface,
and returns JNI_OK.

调试后找到了原因,the current thread is not attached。 原来子线程函数里须要使用AttachCurrentThread()和DetachCurrentThread()这两个函数。没错,你须要gJvm->AttachCurrentThread(&env,
NULL);来获取env,这样写之后,以为万事大吉了,结果findClass出错了,没有找到目标类,但是我千真万确地记得在主线程里这么写是没有问题的。env没有问题了,这回又哪里出错了呢?上网google一番,噢,不正确,google被墙了,是用bing查找一番后,总算有些眉目了。

首先确保你的class name写对了,以包名开头,并用反斜杠隔开。假设class name没有错,那么应该是class loader的问题了。解决方法是你先在主线程中获取该class,而且将其保存为全局变量,以便其它线程使用。
jclass tmp = env->FindClass("com/example/company/MyClass");  

myClass = (jclass)env->NewGlobalRef(tmp);

在子线程中,
mid = env->GetStaticMethodID(cls, "fromJNI", "(I)V");

if (mid != NULL)

{

    env->CallStaticVoidMethod(env, cls, mid, i);

}

当然,也有其它解决方法,至少我使用这样的方法成功了。而接下来在java中调用c++的代码就比較顺利了,木有碰到问题了。

总结:
1.在JNI_OnLoad中,保存JavaVM*,这是跨线程的,持久有效的,而JNIEnv*则是当前线程有效的。一旦启动线程,用AttachCurrentThread方法获得env。
2.通过JavaVM*和JNIEnv能够查找到jclass。
3.把jclass转成全局引用,使其跨线程。
4.然后就能够正常地调用你想调用的方法了。
5.用完后,别忘了delete掉创建的全局引用和调用DetachCurrentThread方法。


怎样在多线程中使用JNI?的更多相关文章

  1. c#初学-多线程中lock用法的经典实例

    本文转载自:http://www.cnblogs.com/promise-7/articles/2354077.html 一.Lock定义     lock 关键字可以用来确保代码块完成运行,而不会被 ...

  2. iOS多线程中,队列和执行的排列组合结果分析

    本文是对以往学习的多线程中知识点的一个整理. 多线程中的队列有:串行队列,并发队列,全局队列,主队列. 执行的方法有:同步执行和异步执行.那么两两一组合会有哪些注意事项呢? 如果不是在董铂然博客园看到 ...

  3. 解决DataGridView在多线程中无法显示滚动条的问题

    在多线程中对DataGridView指定 DataSource 来填充数据,更新数据的时候,会导致DataGridView出现假死,显示错误或者滚动条无法显示的问题,在保证了DataGridView的 ...

  4. iOS开发——多线程OC篇&多线程中的单例

    多线程中的单例 #import "DemoObj.h" @implementation DemoObj static DemoObj *instance; // 在iOS中,所有对 ...

  5. c#语言-多线程中的锁系统(一)

    介绍 平常在多线程开发中,总避免不了线程同步.本篇就对net多线程中的锁系统做个简单描述.   目录 一:lock.Monitor        1:基础.        2: 作用域.       ...

  6. [C#学习]在多线程中如何调用Winform[转]

    问题的产生: 我的WinForm程序中有一个用于更新主窗口的工作线程(worker thread),但文档中却提示我不能在多线程中调用这个form(为什么?),而事实上我在调用时程序常常会崩掉.请问如 ...

  7. Java多线程中易混淆的概念

    概述 最近在看<ThinKing In Java>,看到多线程章节时觉得有一些概念比较容易混淆有必要总结一下,虽然都不是新的东西,不过还是蛮重要,很基本的,在开发或阅读源码中经常会遇到,在 ...

  8. Java多线程中变量的可见性

    之所以写这篇博客, 是因为在csdn上看到一个帖子问的就是这个问题. 废话不多说, 我们先看看他的代码(为了减少代码量, 我将创建线程并启动的部分修改为使用方法引用). 1 2 3 4 5 6 7 8 ...

  9. android中使用jni对字符串加解密实现分析

    android中使用jni对字符串加解密实现分析 近期项目有个需求.就是要对用户的敏感信息进行加密处理,比方用户的账户password,手机号等私密信息.在java中,就对字符串的加解密我们能够使用A ...

随机推荐

  1. Coco2dx-3.0中怎样调用LUA

    一个用3.0的工具导出类到lua,自己主动生成代码的方法. 曾经要导出c++类到lua.就得手动维护pkg文件,那简直就是噩梦.3.0以后就会感觉生活非常轻松了. 以下我就在说下详细做法. 1.安装必 ...

  2. 泛泰A870L/K/S第三版官方4.4.2原来的系统卡刷机包 (愿自己主动ROOT)

    采用suky大神ota具,来自官方的拍摄OTA包裹,未做任何改动, 使用官方recovery,还是我的头发中国TWRP 2.7.1.1 for A870 (己主动ROOT. 自己主动ROOT完后就自己 ...

  3. Parallel Python——一个简单的分布式计算系统

    如何建立一个高速的分布式计算平台?Parallel python此目的. Parallel Python(http://www.parallelpython.com/content/view/15/3 ...

  4. C,C++中的static

    在C和C++中,static都有两种基本的含义,并且这两种含义经常是互相有冲突的: 1) 在固定的地址上分配,也就是说对象是在一个特殊的静态数据区上创建的,而不是每次 函数调用时在堆栈上产生的.这也是 ...

  5. Sandcastle生成帮助文档

    http://www.cnblogs.com/net515/p/3311584.html Sandcastle帮助文档生成器使用介绍 一.软件介绍       Sandcastle是一个管理类库的文档 ...

  6. HBuilder之初体验

    听闻HTML5定稿了,所以特意去了解了下.文章有提到HTML5的一款IDE(HBuilder,貌似出来好久了,孤陋寡闻....),于是来到官网http://dcloud.io/ ,被演示图震惊了!果然 ...

  7. 【原创】leetCodeOj ---Construct Binary Tree from Preorder and Inorder Traversal 解题报告

    原题地址: https://oj.leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/ 题目 ...

  8. 二叉查找树C语言实现

    二叉查找树C语言实现 1.      二叉查找树的定义: 左子树不为空的时候,左子树的结点值小于根节点,右子树不为空时,右子树的结点值大于根节点,左右子树分别为二叉查找树 2.      二叉查找树的 ...

  9. 左右Map

    Person p=new Person("黄雄"); Map map=new HashMap(); map.put("p", p); p.setName(&qu ...

  10. .NET Framework 4.0 以上版本 下载地址

    https://msdn.microsoft.com/zh-cn/library/5a4x27ek(v=vs.110).aspx