1. 程式人生 > >Android 記憶體溢位和記憶體洩漏的區別

Android 記憶體溢位和記憶體洩漏的區別



android記憶體管理

android應用層是由java開發的,android的davlik虛擬機器與jvm也類似,只不過它是基於暫存器的。在java中,通過new為物件分配記憶體,所有物件在java堆內分配空間;而記憶體的釋放是由垃圾收集器(GC)來回收的。 Java採用了有向圖的原理。Java將引用關係考慮為圖的有向邊,有向邊從引用者指向引用物件。執行緒物件可以作為有向圖的起始頂點,該圖就是從起始頂點(GC roots)開始的一棵樹,根頂點可以到達的物件都是有效物件,GC不會回收這些物件。如果某個物件 (連通子圖)與這個根頂點不可達(注意,該圖為有向圖),那麼我們認為這個(這些)物件不再被引用,可以被GC回收。
記憶體溢位就是你要求分配的記憶體超出了系統能給你的,系統不能滿足需求,於是產生溢位。

記憶體溢位(out of memory)

記憶體溢位是指當物件的記憶體佔用已經超出分配記憶體的空間大小,這時未經處理的異常就會丟擲。比如常見的記憶體溢位情況有:bitmap過大;引用沒釋放;資源物件沒關閉

簡單而言,記憶體溢位就是要求分配的記憶體超出了系統能給的,系統不能滿足需求,於是產生溢位。
常見的Bitmap過大所導致的記憶體溢位
如圖,這是常見的bitma物件的溢位,顯示畫素過高或圖片尺寸遠遠大於顯示空間的尺寸時,通常都要將其縮放,減小佔用記憶體。

記憶體溢位的原因

1、記憶體洩露導致

由於我們程式的失誤,長期保持某些資源(如Context)的引用,垃圾回收器就無法回收它,當然該物件佔用的記憶體就無法被使用,這就造成記憶體洩露。

Android 中常見就是Activity被引用在呼叫finish之後卻沒有釋放,第二次開啟activity又重新建立,這樣的記憶體洩露不斷的發生,則會導致記憶體的溢位。

Android的每個應用程式都會使用一個專有的Dalvik虛擬機器例項來執行,它是由Zygote服務程序孵化出來的,也就是說每個應用程式都是在屬於自己的程序中執行的。Android為不同型別的程序分配了不同的記憶體使用上限,如果程式在執行過程中出現了記憶體洩漏的而造成應用程序使用的記憶體超過了這個上限,則會被系統視為記憶體洩漏,從而被kill掉,這使得僅僅自己的程序被kill掉,而不會影響其他程序.
2、佔用記憶體較多的物件

儲存了多個耗用記憶體過大的物件(如Bitmap)或載入單個超大的圖片,造成記憶體超出限制。

記憶體洩漏(memory leak)

有些物件只有有限的生命週期。當它們的任務完成之後,它們將被垃圾回收。如果在物件的生命週期本該結束的時候,這個物件還被一系列的引用,這就會導致記憶體洩漏。隨著洩漏的累積,app將消耗完記憶體。
比如,在Activity.onDestroy()被呼叫之後,view樹以及相關的bitmap都應該被垃圾回收。如果一個正在執行的後臺執行緒繼續持有這個Activity的引用,那麼相關的記憶體將不會被回收,這最終將導致OutOfMemoryError崩潰。
memory leak會最終會導致out of memory!

記憶體洩漏
如圖,這是使用MAT工具查詢記憶體洩漏的結果,例子是 handle 延時傳送 message 而在關閉 activity 後 context 被銷燬所引發的洩漏,這是作為目的性的測試所以問題比較容易找到,在實際開發中記憶體洩漏不易察覺並難以找到,當洩漏累積到一定程度是會引發 OOM 的。

記憶體洩漏的原因

比如當你向系統申請分配記憶體進行使用(new),可是使用完了以後卻不歸還(delete),結果你申請到的那塊記憶體你自己也不能再訪問(也許你把它的地址給弄丟了),而系統也不能再次將它分配給需要的程式。
1.資源物件沒關閉

如Cursor,File等資源。他們會在finalize中關閉,但這樣效率太低。容易造成記憶體洩漏
SQLiteCurost,當資料量大的時候容易洩漏

2.使用Adapter時,沒有使用系統快取的converView
3.沒有即時呼叫recycle()釋放不再使用的bitmap
4.使用application的context來替代activity相關的context

不要讓生命週期長於Activity的物件持有到Activity的引用

5.廣播註冊沒取消造成記憶體洩露
6.Handler應該申明為靜態物件, 並在其內部類中儲存一個對外部類的弱引用。

記憶體洩漏檢測工具

leakcanary

1.記憶體溢位 out of memory
是指程式在申請記憶體時,沒有足夠的記憶體空間供其使用,出現out of memory;比如申請了一個integer,但給它存了long才能存下的數,那就是記憶體溢位。
2.記憶體洩露 memory leak
是指程式在申請記憶體後,無法釋放已申請的記憶體空間,一次記憶體洩露危害可以忽略,但記憶體洩露堆積後果很嚴重,無論多少記憶體,遲早會被佔光。 3.二者的聯絡

記憶體洩露最終會導致記憶體溢位