[英]SoundPoolThread causing SIGSEGV via JNI ERROR "accessed deleted global reference"
我的 Android 應用程序(minSdkLevel:2.2,targetSdkLevel:3.0,在 Nexus 7 和 Android 4.2 上測試)在加載階段執行以下操作:
SoundPool
並在其上注冊一個OnLoadCompleteListener
SoundPool
調用我的回調方法。SoundPool.release()
release()
已經被調用並且之前開始的聲音加載完成,即系統調用我的回調,那么我的應用程序檢測到我的SoundPool
已經為null
並忽略回調,所以它是安全的)。 在 Nexus 7 上進行測試,在調用SoundPool.release()
后SoundPool.release()
出現以下錯誤(logcat):
即事件順序可能如下:
SoundPool.load(...)
調用,系統開始異步加載聲音SoundPool.release()
被調用並且SoundPool
設置為null
我檢查了Android的源代碼,並為JNI代碼SoundPool.release()
確實刪除SoundPool
通過JNI中DeleteGlobalRef
。 它使用弱引用在 Java 級別存儲SoundPool
引用。
我無法重現該錯誤,可能是因為由於不確定性,我無法重現確切條件。 系統應該正確處理SoundPool
在異步加載聲音時可能會被釋放的情況,但似乎在某些極少數情況下會出現錯誤。 (請注意,我的代碼版本SoundPool
一個nullcheck后只出現一次,因此錯誤是不是在我的代碼肯定)。
知道為什么在 Android 中會發生這樣的錯誤嗎? 從理論上講,我的上述懷疑是否正確? 如何保護我的應用程序免受此 Android 錯誤的影響? 也許我可以嘗試在一個布爾值中設置SoundPool
應該被釋放,等到所有回調返回,然后在最后一個回調中釋放它(基於這個布爾值)? 我想不出任何其他解決方法,但我想確定它至少會起作用。
正如您所說,由於競爭條件,這似乎是 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 對象,因此當調用 notify 時,它會嘗試引用此對象,並且會發生“訪問已刪除的全局引用”崩潰。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.