内存泄漏 终结器错误

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个旋转。 输入图像描述 很明显,有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个finalizer引用。我通过Google了解到,JVM在对象即将被GC时将其添加到引用队列中。我期望尽管会发生这种情况,但这些更改在MAT中不会可用,因为我认为GC不需要花费太多时间来释放那些引用。即使我使用13次旋转,结果也相同,有12个finalizer引用。我可能错了,但我认为MAT只会显示1个Activity对象,因为其他对象必须已经被GC了。任何关于终结器引用队列以及垃圾收集过程的帮助都将不胜感激。谢谢。

你尝试过强制进行垃圾回收吗? - Tim B
好的,我没有尝试强制操作。对于第二种情况,我认为GC会自动回收内存,因为没有任何阻止它这样做的东西。将对象放入终结器队列表明该内存确实已准备好被回收,但我的困惑在于为什么在MAT中没有反映出来。 - gaurav jain
1个回答

3

在此输入图片描述

选择 Finalizer 概述。该页面提供等待运行 finalizer、以及其他与 finalizer 线程相关信息的对象数量等信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接