常見記憶體洩露問題

2022-09-13 13:33:13 字數 2687 閱讀 4456

1.資源性物件未關閉

資源性物件(如cursor、file等一些closeable物件),它們往往使用了緩衝區,緩衝區不僅在jvm內,jvm之外也有。如果僅僅把變數設定為null,而不關閉它們,緩衝區得不到釋放,往往造成記憶體洩露。

解決方案:一般在finally中關閉資源型物件,而後設定物件為null

2.註冊物件未登出

訂閱者模式中,如果註冊物件不再使用時,未及時登出,會導致訂閱者列表中維持這物件的引用,阻止垃圾**,導致記憶體洩露。常見場景:動態註冊broadcastreceiver,註冊phonestatelistener,註冊eventbus等等,

還有自定義使用訂閱者模式的情形。

解決方案:一般在ondestroy()中進行解註冊

3.非靜態內部類的靜態例項

使用內部類的情況十分常見,尤其是匿名內部類:一些介面的匿名實現類,都是內部類。

4.單例模式引起的記憶體洩露

由於單例模式的靜態特性,使得它的生命週期和我們的應用一樣長,如果讓單例無限制的持有activity的強引用就會導致記憶體洩漏
5.handler臨時性記憶體洩露

非靜態handler持有activity或service的引用,message中的target指向handler例項,所以當message在messagequeue中排隊,長時間未得到處理時,activity邊不會被**,導致臨時性記憶體洩露。

解決方案:(1)使用靜態handler內部類,然後對handler持有的物件(activity或service)使用弱引用 (2)在ondestroy()中移除訊息佇列中的訊息  mhandler.removecallbacksandmessages(null)

類似的:asynctask內部也是handler機制,也存在同樣的臨時性記憶體洩露風險

6.容器中物件未及時清理導致記憶體洩露

容器類一般擁有較長的生命週期,若內部不再使用的物件不及時清理,內部物件邊一直被容器類引用。上述2中的訂閱者列表也屬於容器類這中情況。另外常見的容器類還有執行緒池、物件池、快取池等。執行緒池中的執行緒若存在threadlocal物件,因為執行緒物件一直被迴圈使用,threadlocal物件便會一直被引用,要注意對value物件的置空釋放。

7.靜態view導致記憶體洩露

有時,當乙個activity經常啟動,但是對應的view讀取非常耗時,我們可以通過靜態view變數來保持對該activity的rootview引用。這樣就可以不用每次啟動activity都去讀取並渲染view了。這確實是乙個提高activity啟動速度的好方法!但是要注意,一旦view attach到我們的window上,就會持有乙個context(即activity)的引用。而我們的view有事乙個靜態變數,所以導致activity不被**。

解決辦法:在使用靜態view時,需要確保在資源**時,將靜態view detach掉

8.屬性動畫未及時關閉導致記憶體洩露

在使用valueanimator或者objectanimator時,如果沒有及時做cancel取消動畫,就可能造成記憶體洩露。 因為在cancel方法裡,最後呼叫了endanimation(); ,在endanimation裡,有個animationhandler的單例,會持有屬性動畫物件的引用

解決辦法:在在ondestory時,呼叫動畫的cancel方法

9.webview記憶體洩露

目前android中webview的實現存在很大的相容性問題,google支援各個rom廠商自行定製自己的webview實現,各個rom間差異較大,且大多都存在記憶體洩露問題。除了呼叫其內部的clearcache()、clearhistory()、removeallviews()、freememory()、destroy()和置null以外,一般比較粗暴有效的解決方法是:將包含webview的activity放在乙個單獨的程序中,不需要時將程序銷毀,從而釋放所有所佔記憶體。

10.其他的系統控制項以及自定義view

在 android lollipop 之前使用 alertdialog 可能會導致記憶體洩漏 

參考:乙個記憶體洩漏引發的血案

dialog和dialogfragment在android5.0以下的記憶體洩漏 

參考:解決android5.0以下dialog引起的記憶體洩漏

view的post方法導致的記憶體洩漏分析

view中有執行緒或者動畫 要及時停止。這是為了防止記憶體洩漏,可以在ondetachedfromwindow方法中結束,這個方法**的時機是 當view的activity退出或者當前view被移除的時候 會呼叫 這時候是結束動畫或者執行緒的好時機 另外還有乙個對應的方法 onattachedtowindow 這個方法呼叫的時機是在包含view的activity啟動時 ** **在ondraw方法之前

11.其他常見的引起記憶體洩漏原因

(1)構造adapter時,沒有使用快取的 contentview

(2)bitmap在不使用的時候沒有使用recycle()釋放記憶體

(3)警惕執行緒未終止造成的記憶體洩露;譬如在activity中關聯了乙個生命週期超過activity的thread,在退出activity時切記結束執行緒。乙個典型的例子就是handlerthread的run方法是乙個死迴圈,它不會自己結束,執行緒的生命週期超過了activity生命週期,我們必須手動在activity的銷毀方法中呼叫thread.getlooper().quit();才不會洩露

(4)避免**設計模式的錯誤造成記憶體洩露;譬如迴圈引用,a持有b,b持有c,c持有a,這樣的設計誰都得不到釋放

記憶體洩露問題

下面是乙個影象去霧的程式,主函式簡略如下,看一下下面的 有何問題。int main cvreleasecapture capture cvdestroywindow result return 0 大致說一下一些fast dahaze是乙個去霧類,負責影象處理,儲存等。程式看起來很簡單,主迴圈裡面做...

記憶體洩露問題

記憶體洩露是vc中自我認為比較難於解決的問題之一 至少現在解決起來很麻煩了 今天用boundschecker除錯了一下原來自己寫的程式,呵呵!居然提示記憶體洩露40位元組。看到了洩露的 的位置,一處new的地方,由於程式寫過很長時間了,所以想不起來了,乾脆模擬一下吧!程式中第一了乙個結構體,用於儲存...

常見的記憶體洩露情況

1,一般來說,alloc都會應該對應乙個release 2,另外,對於autorelease的例項,不能再使用release了 3,對於用類方法建立的例項,無需release,因為在傳遞過來時,已經被autorelease了 4,對於成員變數,一般需要release,途徑有兩個 在alloc建立 使...