android - 无法执行 JavaVM->DetachCurrentThread() : "attempting to detach while still running code"

标签 android c++ android-ndk java-native-interface dalvik

我有一个使用 NDK 的 Android 应用程序 - 一个具有常规 UI 和 C++ 核心的常规 Android Java 应用程序。在核心中有些地方我需要调用 Java 方法,这意味着我需要该线程的 JNIEnv*,这反过来意味着我需要调用 JavaVM->AttachCurrentThread() 获取有效的 env

以前,只是执行 AttachCurrentThread 并且根本没有费心去分离。它在 Dalvik 中运行良好,但一旦调用了 AttachCurrentThread 的线程在未调用 DetachCurrentThread 的情况下退出,ART 就会中止应用程序。所以我阅读了 JNI 引用资料,确实它说我必须调用 DetachCurrentThread。但是当我这样做时,ART 会中止该应用程序并显示以下消息:

attempting to detach while still running code

这里有什么问题,如何正确调用DetachCurrentThread

最佳答案

如果线程在没有分离的情况下退出,Dalvik 也会中止。这是通过 pthread 键实现的——参见 Thread.cpp 中的 threadExitCheck() .

线程可能不会分离,除非它的调用栈是空的。这背后的原因是为了确保在堆栈展开时正确释放任何资源,如监视器锁(即 synchronized 语句)。

按照规范的定义,第二次和后续的附加调用是低成本的空操作。没有引用计数,所以分离总是分离,不管发生了多少次附加。一种解决方案是添加您自己的引用计数包装器。

另一种方法是每次附加和分离。这由应用程序框架在某些回调中使用。这与其说是一个有意的选择,不如说是将 Java 源代码包装在主要用 C++ 开发的代码周围并试图硬塞功能的副作用。如果您查看 SurfaceTexture.cpp ,特别是JNISurfaceTextureContext::onFrameAvailable(),可以看到当SurfaceTexture需要调用Java语言的回调函数时,它会附加线程,调用回调,然后如果线程刚刚被附加它会立即将其分离。 “needsDetach”标志通过调用 GetEnv 来设置,以查看该线程之前是否已附加。

这在性能方面并不是一件好事,因为每个附加都需要分配一个 Thread 对象并执行一些内部 VM 内务处理,但它确实会产生正确的行为。

关于android - 无法执行 JavaVM->DetachCurrentThread() : "attempting to detach while still running code",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27923917/

相关文章:

android - 如何删除原生选项卡的边框

android - Android 上的 Phonegap LocalFileSystem 使用外部存储而不是内部存储

android - React-native-share 在 Android 版本 7 及更高版本中无法正常工作?

c++ - OpenGL 着色器链接

android - 尝试使用 NDK 为 Android 构建 PocketSphinx 时出现问题

android - 动画 Fab 按钮交叉标记

c++ - 如何将QTableWidget高度设置在70以下

c++ - 使用 Win32 读取文件时 glShaderSource 访问冲突

android - 如何在 Android Studio 2.2 Preview 1 中正确使用 NDK-Build

android - 在 Android 上运行 C 程序