なぜJFrameのオブジェクトは、それへの参照が存在しなくても、生き続けるように見えるのでしょうか?

テルアビブコーン:

私の記憶が正しければ、Javaで1を書くことができます

new JFrame();

保存せずにJFrame任意の変数の参照を。このプログラムは、画面上のGUIウィンドウを表示し、プログラムが閉じられるまで、開いたままにしておきます。(この前提が偽であるなら、私を修正してください)。

理論的には、我々は、以来ことを考えることができJFrameGCは、いくつかの点でオブジェクトを解放する必要があり、今でユーザーコードから到達不能です。そしてその結果として、関連するOSのリソース(GUI画面など)がうまくとして解放されます。

しかし、私の理解が正しければ、 - そのプログラムは、(かなり役に立たない1が)有効な作業のJavaプログラムであり、(この前提が間違っている場合は、再度正しい私に)それがどの時点で奇妙な方法でクラッシュしたり、動作しません。

GCが収集することはありませんようだJFrameが、それへの参照がないか、にも関わらず、オブジェクトが、少なくともそれは、関連するOSのリソースが解放されることはありません。

これが可能である方法:私は理解したいと思いますか?

  1. コンストラクタいJFrameセーブでthis任意の場所には、収集されないようにするためには?ソースコードJFrameのスーパーするjava.awt.Frame(方法noteFrame)フレームは、弱参照キューに保存されているように見えます。しかし、これらは弱参照なので、それは物事を説明していないようです

  2. それは、GCがある場合、実際にある最終的に解放JFrameしかし、のファイナライザ方法は- JFrame しない GUIウィンドウの滞在が開くので、関連するOSのリソースを解放するには?

  3. その他の説明は?

これは、より多くの質問へのフォローアップであることをしてください、ノート、私はSE.SEに掲載理論的な質問それはJava実装の詳細に特異的に関係するので、この質問は異なっています。

ホルガー:

A JFrameのみを介して作成されたnew JFrame()任意の追加のアクションなしには、画面上で開かれていませおよびガベージコレクションを防止しません。表示装置に接続されている唯一のフレームは、AWTの実装から参照され、それが明示的に切断されている前に、ガベージコレクションを取得することはできません。

これは次のコードで確認できます。

public static void main(String[] args) {
    check(new JFrame(), "just creating a JFrame", x -> {});
    check(new JFrame(), "creating and connecting a JFrame", JFrame::pack);
    check(Frame.getFrames()[0], "calling dispose()", Frame::dispose);
}
private static <T> void check(T obj, String description, Consumer<T> action) {
    System.out.println(description);
    action.accept(obj);
    WeakReference<T> r = new WeakReference<>(obj);
    obj = null;
    System.gc();
    if(r.get() == null) System.out.println("collected immediately");
    else {
        System.runFinalization();
        System.gc();
        if(r.get() == null) System.out.println("collected after finalization");
        else System.out.println("still alive");
    }
}

これは印刷されます

just creating a JFrame
collected immediately
creating and connecting a JFrame
still alive
calling dispose()
collected after finalization

一般的な実装イ​​ンチ

接続されて以降、上の切断を経由してフレームのに対し、表示装置に接続されることはなかったフレームは、すぐに通常のオブジェクトと同じように収集されることを注意することの価値dispose()通話が最初のガベージコレクタの実行後に行われるクリーンアップのアクションを必要とし、 。

さらに、この例では使用しpack()なくsetVisible(true)フレームが表示されることなく表示装置に接続され得ることができることを実証します。これは、の差になりisDisplayable()成分がスクリーン装置とに接続されているかどうかを反映しisVisible()ているかどうかを指示可視プロパティがに設定されているがtrue最後に、コンポーネントのみを報告しないisShowing()ようtrueには見えると表示されたときに、その親のすべてが表示されます。

おすすめ

転載: http://10.200.1.11:23101/article/api/json?id=392387&siteId=1