我的应用程序中有内存泄漏。在使用VisualVM进行分析后,发现SortedList
中的TableView
会在其内部sorted
数组的末尾保留已删除对象的实例。
我该如何解决这个问题?
使用jdk1.8.0_141
用于演示以下问题的代码(点击表格下方的按钮,最终会得到OutOfMemoryError
):
import java.util.*;
import java.util.stream.*;
import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.*;
import javafx.collections.transformation.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class SortedListTest extends Application {
public static void main(String[] args) {
launch(args);
}
int universeSize = 500;
Universe universe = createUniverse();
ObservableList<Entity> currentEntities = FXCollections.observableArrayList();
@Override
public void start(Stage primaryStage) throws Exception {
currentEntities.addAll(universe.entities);
MyTable table = new MyTable(currentEntities);
TableColumn<Entity, UUID> c1 = new TableColumn<>("C1");
c1.setCellValueFactory(c -> c.getValue().prop1);
table.getColumns().addAll(c1);
Button btn = new Button();
btn.setText(Integer.toString(universeSize));
btn.setOnAction(e -> {
universe = createUniverse();
currentEntities.setAll(universe.entities);
btn.setText(Integer.toString(universeSize));
});
primaryStage.setScene(new Scene(new VBox(table, btn)));
primaryStage.show();
}
Universe createUniverse() {
return new Universe(universeSize--);
}
static class Universe {
final ObservableList<Entity> entities;
final int size;
Universe(int size) {
this.size = size;
this.entities = FXCollections.observableArrayList(
IntStream.range(0, size)
.mapToObj(i -> new Entity(this))
.collect(Collectors.toList())
);
}
}
static class Entity implements Comparable<Entity> {
final byte[] blob = new byte[1024 * 1024];
final SimpleObjectProperty<UUID> prop1 = new SimpleObjectProperty<>(UUID.randomUUID());
final Universe universe;
final double filter = Math.random();
public Entity(Universe universe) {
this.universe = universe;
}
@Override
public int compareTo(Entity o) {
return prop1.get().compareTo(o.prop1.get());
}
}
static class MyTable extends TableView<Entity> {
private ObservableList<Entity> backingList;
private SortedList<Entity> sortedList;
public MyTable(ObservableList<Entity> items) {
super(items);
itemsProperty().addListener(o -> {
ObservableList<Entity> list = getItems();
if (getItems() != sortedList) {
setFilteredList(list);
}
});
setFilteredList(getItems());
}
private void setFilteredList(ObservableList<Entity> backingList) {
this.backingList = backingList;
Comparator<Entity> comparator = sortedList != null ? (Comparator<Entity>) sortedList.getComparator() : Comparator.naturalOrder();
sortedList = backingList.sorted(comparator);
sortedList.comparatorProperty().bind(comparatorProperty());
setItems(sortedList);
}
}
}
在实际代码中,表中的单独列表用于一些其他功能。