简体   繁体   English

JDialog 永远不会被垃圾收集

[英]JDialog is never garbage collected

Why does the following code never garbage collect the JDialog instance?为什么以下代码从不垃圾收集 JDialog 实例? The instance X has no reference and the dialog has been disposed.实例 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();
    }

}

}

Thank you谢谢

The question is (and some of the answers are) mixing two things, garbage collection and finalization.问题是(一些答案是)混合了两件事,垃圾收集和终结。 Runtime.getRuntime().gc() is just a hint that the collection should run and it's very likely that the Dialog has been collected afterward (there's still no guaranty). Runtime.getRuntime().gc() 只是一个提示集合应该运行,很可能之后已经收集了 Dialog(仍然没有保证)。 But this does not mean that the finalizer will run.但这并不意味着终结器会运行。 The virtual machine will avoid running finalize methods as much as it can.虚拟机将尽可能避免运行 finalize 方法。

There is another issue with your test program.您的测试程序还有另一个问题。 JDialog without a parent forces Swing to create an anonymous Frame as parent behind the scenes which will stay alive with unpredictable results (AWT runs within a different thread).没有父级的 JDialog 强制 Swing 在幕后创建一个匿名 Frame 作为父级,这将保持活动状态并产生不可预测的结果(AWT 在不同的线程中运行)。

Try this test program:试试这个测试程序:

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

This works for me.这对我有用。

An alternative to Runtime.getRuntime().gc() is: Runtime.getRuntime().gc() 的替代方法是:

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

as the vm guarantees performing gc before OOME (might not work with 64bit vms;-) ).因为 vm 保证在 OOME 之前执行 gc(可能不适用于 64 位 vm;-))。

The GC calls can't be expected at the specific time.在特定时间不能预期 GC 调用。 It is called randomly or when there is full memory allocated by the JVM.它是随机调用的,或者当有由 JVM 分配的完整 memory 时调用。

PS Your x.dispose(); PS 你的x.dispose(); don't call the GC.不要打电话给GC。 It may just mark that this object can be collected.它可能只是标志着这个object可以被收集。

As was said before - you cannot expect GC at the specific time.如前所述 - 你不能指望在特定时间进行 GC。 But you can "force" it by filling up the memory.但是您可以通过填充 memory 来“强制”它。

try this code, it fills memory after disposing your class.试试这个代码,它在处理你的 class 后填充 memory。 It allocates a lot of Longs in loop but any bigger class would be better.它在循环中分配了很多 Long,但更大的 class 会更好。 (thought thi suffice on my defaults) (认为这对我的默认值就足够了)

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

    }

}

dialog the first one is never GC'ed, and there are some bugs with that, but unfor***, bugsParade is freeze now对话框第一个永远不会被 GC 处理,并且有一些错误,但是 unfor***,bugsParade 现在被冻结

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

The JVM stops before the garbage collection needs to be run. JVM 在需要运行垃圾收集之前停止。 Therefore the JDialog is never garbage collected and thus never finalized.因此, JDialog永远不会被垃圾收集,因此永远不会最终确定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM