具有动态 TableColumns 的 TableView 中的 JavaFX 内存泄漏

JavaFX memory leak in TableView with dynamic TableColumns

我用的是jdk1.8.0_40

我想制作一个可以动态更改列的 TableView,但它会在 Old/Tenured gen 中泄漏内存并最终挂起 JVM。

这是一个演示泄漏的简单程序(不包括导入):

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {    
        TableView<ObservableList<String>> tableView = new TableView<>();
        Button button = new Button("button");

        button.setOnAction((actionEvent) -> {
            // Clearing items and/or columns here doesn't remove the leak
            tableView.getItems().clear();
            tableView.getColumns().clear();

            for (int g = 0; g < 50; g++) { // iterate 50 times to see the leak quickly
                TableColumn<ObservableList<String>, String> tableColumn = new TableColumn<>("column");
                tableView.getColumns().add(tableColumn);
            }
                tableView.getItems().add(FXCollections.observableArrayList("1"));

            // clearing the items here removes the leak somehow, but also makes the table useless
            /* tableView.getItems().clear(); */
        });

        primaryStage.setScene(new Scene(new VBox(tableView, button), 800, 600));
        primaryStage.show();
    }    
    public static void main(String[] args) { launch(args); }
}

在上面的代码中,第二次按下按钮应该会清除所有项目和列,确实如此,但某些引用仍然存在于某处。

一些我已经尝试过的东西:

我最近才开始学习 JavaFX,所以我可能只是遗漏了一些明显的东西,如果是的话 - 抱歉问了一个愚蠢的问题。

如何修复此漏洞?

如果无法修复,是错误,还是这种预期行为,我不应该动态创建 TableColumn?

如果您怀疑存在泄漏,您可以先使用分析器识别它来修复它。

我重写了您的示例(顺便说一句,它没有显示任何数据),似乎没有泄漏。试试这个并检查控制台输出。

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class MainLeak extends Application {

    private static final int iterations = 100;
    private static final int columns = 50;
    private static final int rows = 100;

    @Override
    public void start(Stage primaryStage) {

        TableView<ObservableList<StringProperty>> table = new TableView<>();

        Button button = new Button("button");

        button.setOnAction((actionEvent) -> {

            addData( table, iterations);


        });

        addData( table, iterations);

        primaryStage.setScene(new Scene(new VBox(table, button), 800, 600));
        primaryStage.show();
    }

    private void addData( TableView table, int iterations) {

        for (int i = 0; i < iterations; i++) {

            final int index = i;

            addData(table);

            System.gc();

            System.out.println(index + ": free: " + Runtime.getRuntime().freeMemory() / 1024 + " kb, max: " + Runtime.getRuntime().maxMemory() / 1024 + " kb");

        }

    }

    private void addData(TableView table) {

        table.getItems().clear();
        table.getColumns().clear();

        for( int col=0; col < columns; col++) {
            table.getColumns().add(createColumn(col));
        }

        for( int row=0; row < rows; row++) {
            ObservableList<StringProperty> data = FXCollections.observableArrayList();
            for( int col=0; col < columns; col++) {
                data.add(new SimpleStringProperty(String.valueOf( row + " / " + col)));
            }
            table.getItems().add(data);
        }
    }

    private TableColumn<ObservableList<StringProperty>, String> createColumn(final int columnIndex) {

        TableColumn<ObservableList<StringProperty>, String> column = new TableColumn<>();
        String title = "Column " + columnIndex;
        column.setText(title);
        column.setCellValueFactory(cellDataFeatures -> cellDataFeatures.getValue().get(columnIndex));

        return column;
    }

    public static void main(String[] args) {
        launch(args);
    }
}

回答我自己的问题,以防有人也遇到这个问题 - 这是一个错误。

我提交了一份 JIRA 错误报告,有关更多信息和可能的更新,请参阅 https://javafx-jira.kenai.com/browse/RT-40325