为什么下面的代码从不对 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();
}
}
}
谢谢
最佳答案
问题是(有些答案是)混合垃圾收集和终结这两种东西。 Runtime.getRuntime().gc() 只是提示收集应该运行,很可能之后收集了对话框(仍然没有保证)。但这并不意味着终结器会运行。虚拟机将尽可能避免运行 finalize 方法。
您的测试程序还有另一个问题。没有父级的 JDialog 强制 Swing 在幕后创建一个匿名 Frame 作为父级,它将保持 Activity 状态并产生不可预测的结果(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) {}
因为虚拟机保证在 OOME 之前执行 gc(可能不适用于 64 位虚拟机 ;-))。
关于java - JDialog 永远不会被垃圾回收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5883347/