为什么以下代码永远不会垃圾收集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();
}
}
}
谢谢
答案 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
永远不会被垃圾收集,因此永远不会完成。