JDialog 永远不会被垃圾回收

发布于 2024-11-05 04:35:07 字数 550 浏览 3 评论 0原文

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

}

}

谢谢

Why does the following code never garbage collect the JDialog instance ?
The instance X has no reference and the dialog has been disposed.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

策马西风 2024-11-12 04:35:07

问题是(一些答案是)混合了垃圾收集和终结这两种东西。 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;-))。

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). But this does not mean that the finalizer will run. The virtual machine will avoid running finalize methods as much as it can.

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).

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:

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 ;-) ).

挽袖吟 2024-11-12 04:35:07

无法预期 GC 调用会在特定时间发生。它是随机调用的,或者当 JVM 分配的内存已满时调用。

PS 您的 x.dispose(); 不调用 GC。它可能只是标记这个对象可以被收集。

The GC calls can't be expected at the specific time. It is called randomly or when there is full memory allocated by the JVM.

P.S. Your x.dispose(); don't call the GC. It may just mark that this object can be collected.

彼岸花似海 2024-11-12 04:35:07

正如之前所说 - 你不能指望在特定时间进行 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();
        }

    }

}

As was said before - you cannot expect GC at the specific time. But you can "force" it by filling up the memory.

try this code, it fills memory after disposing your class. It allocates a lot of Longs in loop but any bigger class would be better. (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();
        }

    }

}
久伴你 2024-11-12 04:35:07

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

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

dialog the first one is never GC'ed, and there are some bugs with that, but unfor***, bugsParade is freeze now

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

甜中书 2024-11-12 04:35:07

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

The JVM stops before the garbage collection needs to be run. Therefore the JDialog is never garbage collected and thus never finalized.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文