JDialog永远不会被垃圾收集

时间:2011-05-04 12:27:21

标签: java swing garbage-collection jdialog

为什么以下代码永远不会垃圾收集JDialog实例? 实例X没有引用,对话框已被处理。

public class Test {

public static void main(String[] args) throws Throwable {
    test();

    Runtime.getRuntime().gc();
}

public static void test() throws Throwable {
    X x = new X();
    x.setVisible(true);
    x.dispose();
}

public static class X extends JDialog {

    public X() {
        super();
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("destroyed !");
        super.finalize();
    }

}

}

谢谢

5 个答案:

答案 0 :(得分:2)

问题是(和一些答案是)混合两件事,垃圾收集和完成。 Runtime.getRuntime()。gc()只是一个提示集合应该运行的提示,之后很可能已经收集了Dialog(仍然没有保证)。但这并不意味着终结者将会运行。虚拟机将尽可能避免运行finalize方法。

您的测试程序还有另一个问题。没有父级的JDialog强制Swing创建一个匿名的Frame作为幕后的父级,它将在不可预测的结果中保持活跃状态​​(AWT在不同的线程中运行)。

试试这个测试程序:

import java.lang.ref.WeakReference;

import javax.swing.JDialog;
import javax.swing.JFrame;

public class Test {

public static void main(String[] args) throws Throwable {
    WeakReference<JDialog> ref = test();

    Runtime.getRuntime().gc();
    System.out.println(ref.get()==null? "collected": "still flying around");
  }

  public static WeakReference<JDialog> test() throws Throwable {
      JDialog d = new JDialog(new JFrame());
      WeakReference<JDialog> ref = new WeakReference<JDialog>(d);
      d.setVisible(true);
      d.dispose();
      d.getOwner().dispose();
      return ref;
  }
}

这适合我。

Runtime.getRuntime()的替代方法.gc()是:

try {
    byte[] b = new byte[Integer.MAX_VALUE];
} catch(OutOfMemoryError err) {}

因为vm保证在OOME之前执行gc(可能不适用于64bit vms ;-))。

答案 1 :(得分:1)

在特定时间无法预期GC调用。随机调用或在JVM分配完整内存时调用它。

P.S。您的x.dispose();不会致电GC。它可能只标记可以收集此对象。

答案 2 :(得分:1)

如前所述 - 您不能指望GC在特定时间。但你可以通过填满记忆来“强制”它。

尝试此代码,它会在处理完课程后填充内存。它在循环中分配了很多Longs,但任何更大的类都会更好。 (以为我的默认值就足够了)

public class Test {

    public static void main(String[] args) throws Throwable {
        test();

        Runtime.getRuntime().gc();
    }

    public static void test() throws Throwable {
        X x = new X();
        x.setVisible(true);
        x.dispose();
        //Fill memory:
        for (int i = 0; i < Integer.MAX_VALUE; ++i) {
            Long l = 10L;
        }
    }

    public static class X extends JDialog {

        public X() {
            super();
        }

        @Override
        protected void finalize() throws Throwable {
            System.out.println("destroyed !");
            super.finalize();
        }

    }

}

答案 3 :(得分:0)

对话框第一个从来没有GC,并且有一些错误,但是unfor ***,bugsParade现在冻结

dispose()与GC http://download.oracle.com/javase/6/docs/api/java/awt/Window.html#dispose%28%29

无关

答案 4 :(得分:0)

JVM在需要运行垃圾收集之前停止。因此,JDialog永远不会被垃圾收集,因此永远不会完成。