1

次のコードが 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();
    }

}

}

ありがとうございました

4

5 に答える 5

2

問題は (そしていくつかの答えは) ガベージ コレクションとファイナライズの 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 ビット VM では動作しない可能性があります ;-) )。

于 2012-01-13T14:03:12.440 に答える
1

特定の時間に GC 呼び出しが発生することはありません。ランダムに呼び出されるか、JVM によって割り当てられたメモリがいっぱいになったときに呼び出されます。

PSあなたx.dispose();はGCを呼び出さないでください。このオブジェクトを収集できることを示すだけかもしれません。

于 2011-05-04T12:31:53.310 に答える
1

前に述べたように、特定の時間に 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();
        }

    }

}
于 2011-05-04T12:39:50.147 に答える
0

ダイアログ最初のダイアログはGCされません。それにはいくつかのバグがありますが、残念ながら***、bugsParadeはフリーズします。

dispose()はGCとは何の関係もありませんhttp://download.oracle.com/javase/6/docs/api/java/awt/Window.html#dispose%28%29

于 2011-05-04T12:46:37.017 に答える
0

ガベージ コレクションの実行が必要になる前に、JVM が停止します。したがって、JDialogがガベージ コレクションされることはなく、ファイナライズされることもありません。

于 2011-05-04T12:49:45.010 に答える