1

为什么以下代码从不垃圾收集 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();
    }

}

}

谢谢

4

5 回答 5

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(可能不适用于 64 位 vm ;-))。

于 2012-01-13T14:03:12.440 回答
1

在特定时间不能预期 GC 调用。它是随机调用的,或者当 JVM 分配的内存已满时调用。

PS你x.dispose();不要打电话给GC。它可能只是标志着这个对象可以被收集。

于 2011-05-04T12:31:53.310 回答
1

如前所述 - 你不能指望在特定时间进行 GC。但是你可以通过填满内存来“强制”它。

试试这个代码,它会在处理你的类后填充内存。它在循环中分配了很多 Long,但任何更大的类都会更好。(认为​​这对我的默认值就足够了)

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();
        }

    }

}
于 2011-05-04T12:39:50.147 回答
0

对话框第一个永远不会被 GC 处理,并且有一些错误,但是 unfor***,bugsParade 现在被冻结

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

于 2011-05-04T12:46:37.017 回答
0

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

于 2011-05-04T12:49:45.010 回答