我已经实现了一个在启动过程中由系统服务器调用的服务。
我的服务有JNI实现,它创建了另一个线程。 拥有另一个线程的原因是具有在监视回调时取消操作的能力。
此机制在Android Kitkat版本中运行良好,但在Android L中崩溃。
在两个线程之间,我将从GetJavaVM(env)获取的JavaVM *存储到静态全局变量中。当然,这个共享数据受pthread互斥锁保护。
到目前为止,我已经尝试了以下内容,但下面的所有内容仍然崩溃了:
1)使用JavaVM *我通过将它存储到全局
从JNI onLoad()函数获得2)在新线程中,因为在Android上只运行一个JavaVM,所以从调用android :: AndroidRuntime :: getJavaVM()获取vm;
3)调用NewGlobalRef()后,在主线程中存储vm信息。并保存了对共享数据的引用。新线程使用了NewGlobalRef()的引用。
有没有人知道Android L版本在JNI环境中发生了哪些重大变化?
更新:
进一步调试,我提到的解决方案1)或2)应该有效。 实际问题是由于垃圾收集运行更频繁。所以我保留的HAL指针不再有效......
这些链接很有用!!!
https://developer.android.com/guide/practices/verifying-apps-art.html
http://developer.android.com/training/articles/perf-jni.html
感谢所有评论!
答案 0 :(得分:0)
L版本发生的变化是移植到ART,其失误比Dalvik灵活性低。
在线程之间共享JavaVM *是完全没问题的,你应该保持这种方式。
但是,稍后您使用此JavaVM *做什么?
JNIEnv *必须从同一个线程中检索和使用,不得跨线程使用。要使用JNIEnv *,必须已将一个线程附加到VM(使用AttachCurrentThread
)。
在退出之前,还必须使用DetachCurrentThread
分离线程。