java - SoundPoolThread 通过 JNI 导致 SIGSEGV 错误 "accessed deleted global reference"

标签 java android java-native-interface soundpool

我的 Android 应用程序(minSdkLevel:2.2,targetSdkLevel:3.0,在 Android 4.2 的 Nexus 7 上进行测试)在加载阶段执行以下操作:

  1. 创建一个 SoundPool 并在其上注册一个 OnLoadCompleteListener
  2. 开始加载声音。每当加载声音时,SoundPool 都会调用我的回调方法。
  3. 如果加载过程被用户中断,则会调用 SoundPool.release()
  4. (如果 release() 已被调用并且之前启动的声音加载完成,即系统调用我的回调,那么我的应用程序会检测到我的 SoundPool 已经null 并忽略回调,因此是安全的)。

在 Nexus 7 上进行测试,调用 SoundPool.release() 后 210 毫秒时出现以下错误 (logcat): logcat

即事件顺序可能如下:

  1. 由于我的 SoundPool.load(...) 调用,系统开始异步加载声音
  2. 我离开了加载屏幕,因此调用了 SoundPool.release() 并将 SoundPool 设置为 null
  3. (?)系统完成了较早的声音加载完成回调,但遇到了一些错误。

我检查了Android源代码,SoundPool.release()的JNI代码确实通过DeleteGlobalRef删除了JNI中的SoundPool。它使用弱引用来存储 Java 级别的 SoundPool 引用。

我无法重现该错误,可能是因为由于不确定性而无法重现确切的条件。系统应该正确处理异步加载声音时可能会释放 SoundPool 的情况,但似乎在某些罕见的情况下会出现错误。 (请注意,我的代码在空检查后恰好释放 SoundPool 一次,因此错误肯定不在我的代码中)。

知道为什么 Android 中会发生这样的错误吗?从理论上讲,我的上述怀疑是否正确?如何保护我的应用程序免受此 Android 错误的影响?也许我可以尝试设置一个 boolean 值来释放 SoundPool ,等到所有回调返回,然后在最后一个回调中释放它(基于这个 boolean 值)?我想不出任何其他解决方法,但我想确保它至少会起作用。

最佳答案

正如您所说,由于竞争条件,这似乎是 Android 中的一个错误。根据用户 CommonsWare 的要求,我打开了一个带有回溯的错误:http://code.google.com/p/android/issues/detail?id=53043

有问题的代码似乎位于 Android 的 media/jni/soundpool/SoundPool.cpp 中,其作用是:

void SoundPool::notify(SoundPoolEvent event)
{
    Mutex::Autolock lock(&mCallbackLock);
    if (mCallback != NULL) {
        mCallback(event, this, mUserData);
    }
}

看起来 mCallback 是一个可以被垃圾收集器删除的 Java 对象,因此当调用 notification 时,它会尝试引用该对象,并且会发生“访问已删除的全局引用”崩溃。

关于java - SoundPoolThread 通过 JNI 导致 SIGSEGV 错误 "accessed deleted global reference",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13436470/

相关文章:

android - 检查带有预期分隔符的字符串

android - 从 Eclipse 迁移到 Android Studio 导致问题,应用程序无法启动

android - 如何最小化android wear上的卡片?

java - JNI : Exception in thread "AWT-EventQueue-0" java. lang.UnsatisfiedLinkError 错误

java - Vaadin 按钮操作和消息框需要执行 2 个操作

java - 除了必须计算的值之外还有一个附加条件的动态规划问题

java - Java中的身份验证和 session

java - 与 Activiti 集成时出现 ConversionNotSupportedException

java - QtJambi 4.6.3.2 Windows 7

java - JNI : How to get method signature for debugging purposes