JavaFX SortedList保留已删除对象的实例

时间:2017-11-08 14:39:02

标签: java memory-leaks java-8 javafx-8

我的应用程序中有内存泄漏。在使用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);
    }

}

}

在实际代码中,表中的单独列表用于一些其他功能。

0 个答案:

没有答案