什么是內存泄露
在android項目開發中,通常會有針對應用的性能優化,其中對內存優化是必不可少的環節。在此整理下內存優化中的內存泄露
說到內存泄露(Memory Leak),首先要了解下內存管理。Java的內存管理就是對象的分配和釋放問題。通過關鍵字 new 為每個對象申請內存空間 (基本類型除外);對象的釋放則由 GC 決定和執行的。GC 監控著每一個對象的運行狀態,包括對象的申請、引用、被引用、賦值等。監視對象狀態是為了更加準確地、及時地釋放對象,而釋放對象的根本原則就是該對象不再被引用。
如何判斷對象不可用?
-
引用計數器法(Reference Counting Collector)
引用計數是垃圾收集的 早期策略 。每一個對象都有一個引用計數。一個對象被創建了,并且指向該對象的引用被分配給一個變量,這個對象的引用計數被置為1。當任何其他變量被賦值為對這個對象的引用時,計數加1。當一個對象的引用超過了生存期或者被設置一個新的值時,對象的引用計數減1。任何引用計數為0的對象可以被當作垃圾收集。這種方存在一個問題,如圖所示:循環引用(Circular references)
如圖所示,頂部對象皆不可達,但卻相互引用,基于引用計數器法,則不會被回收。
-
可達性分析法/根集算法( GC Roots )
如圖所示,通過一系列的“GC Roots”的對象作為起始點,從這些節點開始往下搜索,搜索的走過的路徑稱為引用鏈,當一個對象到“GC Roots”沒有引用鏈可達時(也就是用圖論的話說就是從GC Roots到這個對象不可達),則證明此對象是不可用的,這樣的對象被判定為是可回收的。
-
其他GC算法...
綜合以上,可以回答標題的問題了,什么是內存泄露?
答: 某一個對象不再被程序所使用了(無用的對象),但是它卻一直被持有(引用),導致無法正常被gc回收,所占的內存空間無法釋放,那么可以說在這個對象發生了內存泄露
如何判斷一個對象發生了內存泄露?
結合以上說明,我們可以得出結論,不論說明對象,發生內存泄露的條件是:
-
該對象不可用
在程序運行中,不再使用該對象。用圖論的說法是不可達( 這里的不可達有別于5種引用狀態:強可及,弱可及,軟可及,虛可及,不可及 ) -
該對象被持有
這里的被持有指的是被強引用持有,或者是軟引用持有(在內存充裕時,軟引用也會發生內存泄露)
什么對象會內存泄露?
發生內存泄露的2個條件中對象持有是必有條件,所以我們需要關注的引用中兩種引用( 強引用和軟引用 )和引用環境。
-
static 修飾持有
static修飾的成員變量,view,非靜態內部類的靜態實例,尤為值得關注的是 單例模式 -
長連接,持續性的
數據庫連接的關閉,android中動畫是否及時關閉,觀察者模式中注冊對象是否及時取消注冊
-
集合對象清理
在此請參考ArrayList的clear方法
@Override public void clear() { if (size != 0) { Arrays.fill(array, 0, size, null); size = 0; modCount++; } } public static void fill(Object[] array, int start, int end, Object value) { Arrays.checkStartAndEnd(array.length, start, end); for (int i = start; i < end; i++) { array[i] = value; } }
如何查找內存泄露呢?敬請等待下一文
來自:http://www.jianshu.com/p/56f008065246