MediaPlayer原始碼存在的記憶體洩漏問題,釋放資源的正確方式
最近完成了一個聯網的視訊播放器Demo,閒來無聊,嘗試了一下LeakCanary,一款Android檢視記憶體洩漏的工具。使用方式
https://www.liaohuqiu.net/cn/posts/leak-canary-read-me/
這個是LeakCanary的中文使用文件,很簡單。
無意間發現應用存在記憶體洩漏問題。
LeakCanary提供的Log資訊:
D/LeakCanary: In com.shuyu.video.clean.debug:2.0.0:30305.
* com.shuyu.video.activity.PlayActivity has leaked:
* GC ROOT static com.shuyu.video.MyApplication.mApplication
* references com.shuyu.video.MyApplication.mLoadedApk
* references android.app.LoadedApk.mReceivers
* references android.util.ArrayMap.mArray
* references array java.lang.Object[].[3]
* references android.util.ArrayMap.mArray
* references array java.lang.Object[].[2]
* references android.media.MediaPlayer$ProxyReceiver.this$0
* references android.media.MediaPlayer.mProxyContext
* leaks com.shuyu.video.activity.PlayActivity instance
可以看到,這個工具很強大很方便,直接指出了記憶體洩漏的地方,上面寫的很清楚,倒數第二行說明了Mediaplayer存在一個代理引用,導致了PlayActivity無法回收,造成記憶體洩漏。
按理說,既然工具已經這麼詳細的說明了記憶體洩漏出現問題的地方,問題應該很好解決,但是,我檢視了我的程式碼,mediaplayer容易出現記憶體洩漏的地方無非就是在和Activity進行生命週期的時候,需要自己進行釋放資源,不然會造成記憶體洩漏。
附上我的關鍵程式碼吧:
@Override
protected void onDestroy() {
super.onDestroy();
ReleasePlayer();
}
/**
* 釋放播放器資源
*/
private void ReleasePlayer() {
if (player != null) {
player.stop();
player.release();
player = null;
}
}
可以看到我重寫了Activity的生命週期,在OnDestroy方法中釋放了Mediaplayer的資源,釋放Mediaplayer的資源的方法也是網路上常用的釋放Meidplayer的步驟。但是問題來了,這樣怎麼會造成記憶體洩漏哪?
最後,還是老外厲害啊,在stackoverflow上找到一篇文章,問題一模一樣,原文連結
大概意思是,他檢視了Mediaplayer的原始碼,發現存在一個引用,應該回收,但是在release方法中,並沒有沒處理,只有在reset方法中,這個引用才被消除。
所以結論來了:釋放資源的正確方式:
/**
* 釋放播放器資源
*/
private void ReleasePlayer() {
if (player != null) {
player.stop();
//關鍵語句
player.reset();
player.release();
player = null;
}
}
具體到原始碼,是哪一個沒有回收,大概看了一下
Mediaplayer的release原始碼:
public void release() {
baseRelease();
stayAwake(false);
updateSurfaceScreenOn();
mOnPreparedListener = null;
mOnBufferingUpdateListener = null;
mOnCompletionListener = null;
mOnSeekCompleteListener = null;
mOnErrorListener = null;
mOnInfoListener = null;
mOnVideoSizeChangedListener = null;
mOnTimedTextListener = null;
if (mTimeProvider != null) {
mTimeProvider.close();
mTimeProvider = null;
}
mOnSubtitleDataListener = null;
_release();
}
reset的原始碼:
public void reset() {
mSelectedSubtitleTrackIndex = -1;
synchronized(mOpenSubtitleSources) {
for (final InputStream is: mOpenSubtitleSources) {
try {
is.close();
} catch (IOException e) {
}
}
mOpenSubtitleSources.clear();
}
if (mSubtitleController != null) {
mSubtitleController.reset();
}
if (mTimeProvider != null) {
mTimeProvider.close();
mTimeProvider = null;
}
stayAwake(false);
_reset();
// make sure none of the listeners get called anymore
if (mEventHandler != null) {
mEventHandler.removeCallbacksAndMessages(null);
}
synchronized (mIndexTrackPairs) {
mIndexTrackPairs.clear();
mInbandTrackIndices.clear();
};
}
我查了reset中的物件,發現mSubtitleController 這個物件在release方法中沒有被處理,只在reset方法中被reset了,並且mSubtitleController 的構造方法會存在context物件,我猜應該就是這個物件,導致記憶體洩漏這個問題存在吧
mSubtitleController = new SubtitleController(context, mTimeProvider, MediaPlayer.this);
問題的正確與否,具體原始碼原理和原因待求大神解釋。
相關文章
- 記憶體的分配與釋放,記憶體洩漏記憶體
- 記憶體洩漏問題分析之非託管資源洩漏記憶體
- 正確釋放Vector的記憶體記憶體
- AFN的記憶體洩漏問題記憶體
- HibernateDaoSupport 記憶體洩漏的問題!記憶體
- 記憶體洩漏引起的 資料庫效能問題記憶體資料庫
- 關於PHP記憶體洩漏的問題PHP記憶體
- ThreadLocal記憶體洩漏問題thread記憶體
- redisson記憶體洩漏問題排查Redis記憶體
- 納尼,Java 存在記憶體洩洩洩洩洩洩漏嗎?Java記憶體
- iOS八種記憶體洩漏問題iOS記憶體
- iOS 11 textField記憶體洩漏問題iOS記憶體
- bea記憶體洩漏問題診斷記憶體
- .NET 記憶體管理兩種有效的資源釋放方式記憶體
- 記憶體洩漏的原因記憶體
- BufferedImage記憶體洩漏和溢位問題記憶體
- 記憶體洩漏記憶體
- 解決記憶體洩漏(1)-ApacheKylin InternalThreadLocalMap洩漏問題分析記憶體Apachethread
- 分析ThreadLocal的弱引用與記憶體洩漏問題thread記憶體
- 對於記憶體洩漏問題的簡單認知記憶體
- 我是如何搞定 NodeJS 記憶體洩漏問題的NodeJS記憶體
- 如何解決JVM OutOfMemoryError記憶體洩漏問題?JVMError記憶體
- WebView引起的記憶體洩漏WebView記憶體
- ARC下的記憶體洩漏記憶體
- 【轉】Java的記憶體洩漏Java記憶體
- 分析記憶體洩漏和goroutine洩漏記憶體Go
- 【Java面試題】之記憶體洩漏Java面試題記憶體
- 使用 Chrome Dev tools 分析應用的記憶體洩漏問題Chromedev記憶體
- handlder引起的記憶體洩漏問題以及解決辦法記憶體
- ThreadLocal會不會有所謂“記憶體洩漏”的問題thread記憶體
- 急!請教用optimizeit檢測記憶體洩漏的問題?記憶體
- js記憶體洩漏JS記憶體
- Java記憶體洩漏Java記憶體
- webView 記憶體洩漏WebView記憶體
- Javascript記憶體洩漏JavaScript記憶體
- 一篇文章,從原始碼深入詳解ThreadLocal記憶體洩漏問題原始碼thread記憶體
- Swift的ARC和記憶體洩漏Swift記憶體
- .NET 記憶體洩漏的爭議記憶體