2015-04-15 50 views
7

我一直在研究內存泄漏並使用內存分析工具來檢查它們。所以,作爲一種實踐,我有下面的代碼泄露一項活動,因爲匿名內部類擁有對活動的引用。下面的代碼:內存泄漏終結者錯誤

public class MainActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    exampleOne(); 
    } 

    private void exampleOne() { 
    new Thread() { 
     @Override 
     public void run() { 
     while (true) { 
      SystemClock.sleep(1000); 
     } 
     } 
    }.start(); 
    } 
} 

我對這裏上述泄漏存儲器分析器圖像(6轉):6 Rotations of the activity. enter image description here

這是相當清楚的是有6級保持於外的隱式引用運行的線程活動,從而防止垃圾被垃圾收集。

現在,請考慮下面的代碼:

public class MainActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    exampleTwo(); 
    } 

    private void exampleTwo() { 
    new MyThread().start(); 
    } 

    private static class MyThread extends Thread { 
    @Override 
    public void run() { 
     while (true) { 
     SystemClock.sleep(1000); 
     } 
    } 
    } 
} 

在這裏,我所做的類的靜態,從而使有到外的活動沒有參考和GC可以自由回收活動對象,而不由線程被阻止類。

下面是相同的MAT截圖:6 Rotations again.

enter image description here

我有關於第二組截圖,其中有5所終結引用的混亂。我搜索了一下,發現JVM在對象被加入GC之後會將這些對象添加到引用隊列中。我預計,雖然會發生這種情況,但MAT中不會提供這些更改,因爲我認爲GC不會花費太多時間來釋放這些引用。即使我使用13次旋轉,結果也是一樣的,有12次終結器參考。我可能是錯的,但我認爲MAT只會顯示1個Activity對象,因爲其他人必須已經被GCed。任何關於最終化引用隊列的幫助,以及在垃圾回收時繼續進行的過程,我們將不勝感激。謝謝。

+0

你試過強制垃圾收集嗎? –

+0

好吧,不,我沒有嘗試過強迫。對於第二種情況,我認爲GC會自動回收內存,因爲沒有任何阻止它的做法。將對象放入終結器隊列中表明確實已經準備好回收內存了,但是我的困惑是爲什麼它沒有在MAT中反映出來。 –

回答

3

enter image description here

選擇終結器概述。它提供了有關等待終結器運行的對象數量以及終結器線程的其他相關信息。