我一直在研究内存泄漏并使用内存分析器工具来检查它们.所以,作为一种做法,我有以下代码泄漏活动,因为匿名内部类持有对活动的引用.这是代码:
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个运行线程持有对外部活动的隐式引用,从而防止它被垃圾收集.
现在,请考虑以下代码:
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可以自由地回收Activity对象而不会被线程类阻止.
以下是相同的MAT屏幕截图:
我对第二组截图感到困惑,其中有5个终结器引用.我搜索了它,发现JVM一旦将要进行GCed就将对象添加到引用队列中.我预计,尽管会发生这种情况,但MAT中不会提供这些更改,因为我认为GC不会花费太多时间来释放这些参考.即使我使用13次旋转,结果也是相同的,有12个终结器参考.我可能错了,但我认为MAT只显示1个Activity对象,因为其他人必须已经GCed.有关最终化参考队列的任何帮助,以及在垃圾收集过程中继续进行的过程.谢谢.
解决方法
选择Finalizer概述.它提供有关等待终结器运行的对象数量以及终结器线程的其他相关信息的信息.