2015-04-15 49 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

选择终结器概述。它提供了有关等待终结器运行的对象数量以及终结器线程的其他相关信息。