简体   繁体   English

更新JavaFX BarChart数据会导致内存泄漏

[英]Updating JavaFX BarChart data causes memory leak

I've discovered what I believe is a memory leak in JavaFX (1.8u40 GA and 1.8u60 b10 EA) BarChart triggered by replacing all the data values in the series. 我发现我认为是JavaFX(1.8u40 GA和1.8u60 b10 EA) BarChart中的内存泄漏,是通过替换系列中的所有数据值触发的。 This is exasperated by our application which does this several times a second. 我们的应用程序每秒执行几次此操作,这很恼火。

Using jvisualvm shows an uncontrolled growth in the number of javafx.scene.layout.StackPane instances which eventually results in an OutOfMemoryError. 使用jvisualvm显示javafx.scene.layout.StackPane实例的数量不受控制地增长,最终导致OutOfMemoryError。 Styled StackPane nodes are used internally by BarChart for the bars. BarChart在内部将样式化的StackPane节点用于条形图。

I've tried a different strategies to update the list. 我尝试了其他策略来更新列表。 All exhibit the same issue. 所有都显示相同的问题。

// 1
series.getData().clear();
series.getData().addAll(list);
// 2
series.getData().setAll(list);
// 3
series.setData(list)

Interestingly the example in the Oracle BarChart tutorial updates values by adding all the bars/points first, and then mutating them using XYChart.Data.setYValue() . 有趣的是, Oracle BarChart教程中的示例通过首先添加所有条形/点,然后使用XYChart.Data.setYValue()对其进行变异来更新值。 This could work, but is not convenient for us as the number of data points can vary dynamically. 这可能有效,但对我们来说并不方便,因为数据点的数量会动态变化。

Specific questions 具体问题

  • Is there anyway to avoid this issue, other than a extra logic using the setYValue() approach above. 除了使用上面的setYValue()方法的额外逻辑之外,是否还有其他方法可以避免此问题。
  • Have I stumbled across an actual memory leak in JavaFX? 我是否偶然发现了JavaFX中的实际内存泄漏? or just an artefact of my misuse of the API? 还是我滥用API的伪像? Surely freeing internal nodes when data is updated is JavaFX responsibility 确保在数据更新时释放内部节点是JavaFX的责任

Example

public class ChartUpdate extends Application {
    private int clock;
    public static void main(String[] args) {
        launch(args);
    }
    @Override
    public void start(Stage stage) {
        CategoryAxis xAxis = new CategoryAxis();
        NumberAxis yAxis = new NumberAxis(0, 100, 10);
        yAxis.setAutoRanging(false);
        BarChart<String, Number> graph = new BarChart<>(xAxis, yAxis);
        graph.setAnimated(false);
        Series<String, Number> series = new Series<>();
        graph.getData().add(series);
        stage.setScene(new Scene(graph));
        stage.show();

        Timeline timeLine = new Timeline();
        timeLine.getKeyFrames().add(
                new KeyFrame(Duration.millis(500),
                        (e) -> {
                            ObservableList<Data<String, Number>> list = FXCollections.observableArrayList();
                            for (int i = 0; i < 100; i++) {
                                list.add(new Data<>(String.valueOf(i), (clock + i) % 100));
                            }
                            series.setData(list);
                            clock++;
                        }));
        timeLine.setCycleCount(Animation.INDEFINITE);
        timeLine.play();
    }
}

In summary this was a genuine issue accepted by JavaFX team and fixed by JDK-8094805 in 8u60 总之,这是JavaFX团队接受的真实问题,并由JDK-8094805在8u60中修复

See https://bugs.openjdk.java.net/browse/JDK-8094805 for more detail. 有关更多详细信息,请参见https://bugs.openjdk.java.net/browse/JDK-8094805

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM