什么是內存泄露

在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

 

 本文由用戶 RenatoLapsl 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!