我使用的是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?
回答我自己的问题,以防有人也遇到这个问题 - 这是一个错误。
我提交了 JIRA 错误报告,有关更多信息和更新,请参阅 https://javafx-jira.kenai.com/browse/RT-40325
如果您怀疑存在泄漏,请首先使用分析器进行识别来修复它。
我重写了你的示例(顺便说一句,它没有显示任何数据),似乎没有泄漏。尝试这个并检查控制台输出。
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);
}
}
我想问一下,为什么https://javafx-jira.kenai.com/browse/RT-40325这个连接打不开,是问题解决了吗?如果解决了,是怎么解决的