2011-05-04 38 views
1

为什么下面的代码永远不会垃圾收集JDialog实例? 实例X没有参考,并且对话框已被处理。JDialog永远不会垃圾收集

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

} 

} 

谢谢

+3

只是一般性的建议:你既不能期望'gc()'执行垃圾回收,也不能'调用'finalize()。你不应该依赖'gc()',这是没有必要的。你永远不应该永远不要依赖'finalize()'。 – musiKk 2011-05-04 12:49:31

回答

2

问题是(和一些答案是)混合两件事,垃圾收集和定稿。 Runtime.getRuntime()。gc()只是集合应该运行的一个暗示,很可能以后收集了对话框(仍然没有保证)。但这并不意味着终结者将会运行。虚拟机将尽可能避免运行最终化方法。

您的测试程序还有另一个问题。不带父级的JDialog强制Swing在幕后创建一个匿名框架,这些框架将随着不可预知的结果(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位虚拟机;-)工作)。

1

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

P.S.您的x.dispose();不会拨打GC。它可能标志着这个对象可以被收集。

+0

Runtime.getRuntime()。gc();应该打电话给gc? – 2011-05-04 12:45:21

+0

它可能会调用,但不能保证在您需要时收集对象。无论如何,当您使用大量数据时,您只应该注意这种方法。 – StKiller 2011-05-04 12:59:37

1

正如之前所说 - 你不能指望GC在特定的时间。但是你可以通过填充内存来“强制”它。

试试这段代码,它会在处理完你的类之后填充内存。它在循环中分配了很多Longs,但是任何更大的类都会更好。 (以为我默认THI足够了)

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

    } 

} 
0

对话框中的第一个是从未GC'ed,并有一些错误与,但unfor ***,bugsParade是冷冻现在

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

+0

我知道dispose与GC无关。但是如果你调用dispose,那么系统资源应该被删除,当我调用Runtime.getRuntime()。gc(); gc应该完成对话框实例? – 2011-05-04 12:49:12

+0

@Joachim Sauer感谢您与Java6,@ Benjamin Leclerc的链接,如果您是JProfiler的家庭成员,那么您可以通过简单的方式了解JVM实例如何与对象和方法一起工作,并使用实时对象,JDialog的API有一些错误:DISPOSE_ON_CLOSE (在WindowConstants中定义):在调用任何已注册的WindowListener对象后,自动隐藏和处理对话框。 – mKorbel 2011-05-04 13:06:46

0

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