android ndk 线程,NDK 线程的一些坑与解决措施

原标题:NDK 线程的一些坑与解决措施

作者:何晓杰

本文为原创文章,转载请注明作者及出处

自从换了某个版本的 NDK 后,就一直坑不断,踩了几天之后,发现在线程部分坑已然变多,必须好好解决一下了。

首先讲一下线程的问题,目前建议将所有可能会耗时的函数都放进线程,原因是现在的 NDK 似乎可能好像也许会在意料不到的地方 ANR,比如以下代码:

clsContext:= env^^.FindClass(env, 'android/content/Context');

getServiceContet:= env^^.GetMethodID(env, clsContext, 'getSystemService', '(Ljava/lang/String;)Ljava/lang/Object;');

objActivityMgr:= env^^.CallObjectMethodA(env, CONTEXT, getServiceContet, argsToJValues(env, [ 'activity']));

你能想象这会产生一个 ANR 吗?可能我们都没有注意过这样的问题,认为这种情况没有 ANR 的可能,然而通过实际采集的 bug 告诉我们,这样的代码在 NDK 里,ANR 的机率大概在 0.2% 左右,所以这跟本不是什么能侥幸的事情。

所以将这样的代码放进线程,是很有必要的。那么下面就开始遇到坑,比如说:

clsContext:= env^^.FindClass(env, 'android/content/Context');

很可惜的,在线程里若是这么干,FindClass 得到的结果永远是 nil,原因是子线程里的 JNIEnv 与主线程里的不同,因此找不到类。好吧,那么就在主线程里先完成 FindClass 吧。

varclsContext: jclass;

...

procedure ...

clsContext := env^^.FindClass(env, 'android/content/Context');

...

看起来解决了?其实不然,实际用一下就知道了,比如说用以下代码:

thread { NativeAPI.run() }

这个时候依然会从 JNI 层抛出 accessed stale local reference 异常,引起闪退。这个闪退的原因是,局部的引用在函数结束时,已被清理。若是用老版本的 NDK 进行编译,并不会产生此问题。那么在新版本下,就需要额外多做一件事了:

varclsContext: jclass;

...

procedure ...

clsContext := env^^.NewGlobalRef(env, env^^.FindClass(env, 'android/content/Context'));

...

至此,搞定了在线程里面 FindClass 的问题,当然了,你也可以选择用 AttachCurrentThread 的方案,不再赘述。

End

责任编辑:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值