10

JavaFxボタンをクリックすると new でテーブルが開くアプリケーションを作成していますstage。しかし、私の問題は、stageそのテーブルを閉じると、アプリケーションによってメモリが解放されないことです。javaFXに問題はありますか?または私は何か他のことをしなければなりませんか?

そのステージの終了時にすべてを null に設定しようとしましたが、それでもメモリが解放されません。

テーブル のステージでのクロージング イベント:

TableView テーブルビュー;

ステージ myStage;

this.myStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
            @Override
            public void handle(WindowEvent t) {
                TableController.this.myStage.close();
                tableView.getItems().clear();
                tableView.getColumns().clear();
                tableView = null;
                TableController.this.myStage = null;
                System.gc();
            }
        });

ステージ用のファイルを使用してシーンをロードするために、 replaceSceneというメソッドを作成しました。fxmlコントローラとセット シーンをステージに戻します。

 public static Initializable replaceScene(String fXml, Stage mystage) {
    InputStream in = null;
    try {
        FXMLLoader loader = new FXMLLoader();
        in = Utility.class.getResourceAsStream(fXml);
        loader.setLocation(Utility.class.getResource(fXml));
        loader.setBuilderFactory(new JavaFXBuilderFactory());
        AnchorPane page;
        try {
            page = (AnchorPane) loader.load(in);
        } finally {
            in.close();
        }
        Scene scene = new Scene(page);
        mystage.setScene(scene);
        return loader.getController();
    } catch (Exception ex) {
        return null;
    }
}

最初に fxml ファイルの StreamObject (java.io.InputStream) を取得してから、この streamObject を FxmlLoader に渡してページを読み込みます。

in = Utility.class.getResourceAsStream(fXml);

入力ストリームオブジェクトでsun.net.www.protocol.jar.JarURLConnection$JarURLInputStreamのオブジェクト取得しています

4

2 に答える 2

8

メモリ管理と JavaFX に特別なことは何もありません。定義されたメモリ制限に達すると、GC が実行されます。object = null に設定した後は実行されません。呼び出してもSystem.gc()、GC が実行されるわけではありません。Javadocから:

gc メソッドを呼び出すことは、Java 仮想マシンが未使用のオブジェクトをリサイクルして、現在占有しているメモリをすばやく再利用できるようにすることを示唆しています。

どこかにメモリ リークがあるかどうかを判断するには、たとえばVisualVMを使用して、アプリケーションがメモリ不足になるかどうか (およびその理由) を確認します。

于 2013-02-26T10:19:25.700 に答える
2

私は非常によく似た質問を投稿しようとしていました。私は訓練を受けたソフトウェア エンジニアではないことを告白しなければなりません。私のアプリ開発スタイルは、おそらく「微妙な」プラクティスやスタイルに依存しています。私が Java で気に入っている点の 1 つは、組み込みのメモリ管理です。Java で気に入らない点の 1 つは、組み込みのメモリ管理です。

たとえば、Visual Basic 6 では、オブジェクトの参照カウントがゼロになると、そのオブジェクトは確実に破棄されます。Visual Basic 6 でのモーダル ダイアログ ウィンドウの実装は非常に簡単でした。

Set myForm = new frmGetClientData
Call myForm.Initialize()
myForm.show, vbModal
nResult = myForm.getResult()
myForm.Hide()
Set myForm = nothing

myForm への参照がクリアされるとすぐに破棄されます。これは、毎回新しいフォームが作成されて初期化されることが保証されているので便利でした。

Java では、モーダル ダイアログ ウィンドウを操作するのは非常に困難です。ダイアログ コントローラー オブジェクトは、参照が渡されない限り、親コントローラー オブジェクトについて何も知りません。同様に、親コントローラー オブジェクトは、メソッドを呼び出す必要がある場合、ダイアログ コントローラーへの参照を取得する必要があります。親コントローラーは、新しいステージを構築しているため、ダイアログ ステージのモダリティをモーダルに設定するために、独自のステージへの参照を取得する必要があります。

これらすべての参照が前後を指しているため、Javaではモーダルダイアログウィンドウがガベージコレクションされることはないように思えます(親ウィンドウとコントローラーを指す参照は有効なままである必要があるため)...そして毎回FXMLLoader を使用してダイアログ ウィンドウを構築および表示すると、新しい大きなオブジェクトが非常に長い寿命でメモリに格納されます。Java でモーダル ダイアログ ウィンドウを使用すると、メモリ リークが発生するように思えます。

解決策の 1 つは、Visual Basic モードに移行し、使用されなくなったダイアログ ウィンドウやコントローラーとの間で参照を解放することに注意を払うことです。なんて面倒。これは、ウィンドウがいつ破棄されるかについての保証をまだ提供していません。

もう 1 つの解決策は、ダイアログ ウィンドウを表示するたびに新しいウィンドウを作成するのではなく (Visual基本)。

JavaFXでこれについての洞察を持っている人はいますか? モーダル ダイアログ ウィンドウの作成と管理を支援するヘルパー クラスを作成中ですが、これは本当に必要ではないように思えます。私は自分のために余分な仕事をしているだけかもしれません。

于 2013-03-01T06:42:13.023 に答える