Memory JavaFX-内存消耗

Memory JavaFX-内存消耗,memory,javafx,Memory,Javafx,我有一个巨大的JavaFX应用程序,主要使用FXML文件来创建视图,我注意到内存使用率很高,但已经忽略了一段时间。经过调查,我发现每个视图都消耗了大量的内存,但是,在关闭表单垃圾收集器之后,使用的内存被释放。 例如,滚动抛出一个包含约1000个元素的表视图[附屏幕截图],内存使用量从350 MB激增到780 MB 滚动列表视图时也会发生同样的情况,该列表视图显示了表视图的相同数据: 问题是,这正常吗?或者我可能做错了什么 更新 对于表视图,我正在执行以下操作以生成列: public st

我有一个巨大的JavaFX应用程序,主要使用FXML文件来创建视图,我注意到内存使用率很高,但已经忽略了一段时间。经过调查,我发现每个视图都消耗了大量的内存,但是,在关闭表单垃圾收集器之后,使用的内存被释放。 例如,滚动抛出一个包含约1000个元素的表视图[附屏幕截图],内存使用量从350 MB激增到780 MB

滚动列表视图时也会发生同样的情况,该列表视图显示了表视图的相同数据:

问题是,这正常吗?或者我可能做错了什么

更新

对于表视图,我正在执行以下操作以生成列:

public static <T> TableColumn<T, T> generateGraphicColumn(String title, Callback<TableColumn<T, T>, TableCell<T, T>> callback) {
    TableColumn<T, T> column = generateColumn(title, null);
    column.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<T, T>, ObservableValue<T>>() {

        @Override
        public ObservableValue<T> call(CellDataFeatures<T, T> param) {
            SimpleObjectProperty<T> s = new SimpleObjectProperty<>();
            s.setValue(param.getValue());
            return s;
        }
    });
    column.setCellFactory(callback);
    return column;
}

public static <T> TableColumn<T, T> generateGraphicColumn(String title, Callback<TableColumn<T, T>, TableCell<T, T>> callback, double width) {

    TableColumn<T, T> column = generateGraphicColumn(title, callback);
    column.setMaxWidth(width);
    column.setMinWidth(width);
    return column;

}
public static <T,S> TableColumn<T, S> generateColumn(String title,
        Callback<TableColumn.CellDataFeatures<T, S>, ObservableValue<S>> propertyValueFactory) {

    TableColumn<T, S> column;
    column = new TableColumn<>();
    if (propertyValueFactory != null)
        column.setCellValueFactory(propertyValueFactory);
    column.setStyle(column.getStyle() + "-fx-alignment: BASELINE_CENTER;");
    column.setText(title);
    return column;

}
publicstatictablecolumn generateGraphicColumn(字符串标题,回调){
TableColumn column=generateColumn(标题,null);
column.setCellValueFactory(新回调(){
@凌驾
公共observeValue调用(CellDataFeatures参数){
SimpleObjectProperty s=新的SimpleObjectProperty();
s、 setValue(param.getValue());
返回s;
}
});
column.setCellFactory(回调);
返回列;
}
公共静态TableColumn generateGraphicColumn(字符串标题、回调、双宽度){
TableColumn column=generateGraphicColumn(标题,回调);
column.setMaxWidth(宽度);
列。设置最小宽度(宽度);
返回列;
}
公共静态表列generateColumn(字符串标题,
回调属性(值工厂){
表列;
column=新表column();
if(propertyValueFactory!=null)
column.setCellValueFactory(propertyValueFactory);
column.setStyle(column.getStyle()+“-fx对齐:基线_中心;”);
列.setText(标题);
返回列;
}
我使用的代码如下所示:

    { // status
        TableColumn<Visit, Visit> column = TableViewUtilities.generateGraphicColumn(text("General.STATUS"),
                new Callback<TableColumn<Visit, Visit>, TableCell<Visit, Visit>>() {
                    @Override
                    public TableCell<Visit, Visit> call(final TableColumn<Visit, Visit> param) {
                        final TableCell<Visit, Visit> cell = new TableCell<Visit, Visit>() {

                            @Override
                            public void updateItem(Visit item, boolean empty) {

                                super.updateItem(item, empty);


                                if (empty || getIndex() < 0) {
                                    setGraphic(null);
                                    setText(null);
                                    return;
                                }

                                item = getTableView().getItems().get(getIndex());

                                Label label = new Label();
                                StackPane pane = new StackPane(label);
                                pane.setAlignment(Pos.CENTER);
                                label.setMaxWidth(10);
                                label.setMinWidth(10);
                                label.setMinHeight(30);

                                setText(item.getStatus().display());
                                String background = FXMLConstants .toHexString(ColorUtils.getVisitBackgroundColor(item));
                                pane.setStyle(String.format("-fx-background-color:%s;;", background));
                                setGraphic(pane);
                                setText(item.getStatus().display());
                                setStyle(getStyle() + "-fx-alignment: CENTER_LEFT;");
                            }
                        };
                        return cell;
                    }
                }, 100);

        column.setComparator(VisitCommonHelper.getCompByStatus());
        tblVisits.getColumns().add(column);
    }
{//status
TableColumn column=TableViewUtilities.generateGraphicColumn(文本(“General.STATUS”),
新回调函数(){
@凌驾
公共TableCell调用(最终TableColumn参数){
最终TableCell单元格=新TableCell(){
@凌驾
public void updateItem(访问项,布尔值为空){
super.updateItem(项,空);
if(空| | getIndex()<0){
设置图形(空);
setText(空);
返回;
}
item=getTableView().getItems().get(getIndex());
标签=新标签();
StackPane pane=新的StackPane(标签);
窗格设置对齐(位置中心);
标签。设置最大宽度(10);
标签设置最小宽度(10);
标签设置最小高度(30);
setText(item.getStatus().display());
String background=fxmlstants.toHexString(ColorUtils.getVisitBackgroundColor(item));
pane.setStyle(String.format(“-fx背景色:%s;;”,背景));
设置图形(窗格);
setText(item.getStatus().display());
setStyle(getStyle()+“-fx对齐:中间左;”;
}
};
返回单元;
}
}, 100);
setComparator(VisitCommonHelper.getCompByStatus());
tblVisits.getColumns().add(column);
}

您正在为每个非空单元格更新创建一个新的
标签
堆栈窗格
,这可能解释了堆使用率上升但可能被垃圾收集的原因

您可以尝试通过缓存节点来解决此问题(
Label
StackPane
中,在您的情况下)-仅创建一次:

final TableCell<Visit, Visit> cell = new TableCell<Visit, Visit>() {
    private Label label;
    private StackPane pane;
    {
        // This is the constructor of the anonymous class. Alternatively, you may choose to create the label and pane lazily the first time they're needed. 
        label = new Label();
        pane = new StackPane(label); 
        pane.setAlignment(Pos.CENTER);
        label.setMaxWidth(10);
        label.setMinWidth(10);
        label.setMinHeight(30);
    }

    @Override
    public void updateItem(Visit item, boolean empty) {
        super.updateItem(item, empty);
        if (empty || getIndex() < 0) {
            setGraphic(null);
            setText(null);
            return;
        }
        item = getTableView().getItems().get(getIndex());

        setText(item.getStatus().display());

        String background = FXMLConstants.toHexString(ColorUtils.getVisitBackgroundColor(item));
        pane.setStyle(String.format("-fx-background-color:%s;;", background));
        setGraphic(pane);
        setText(item.getStatus().display());
        setStyle(getStyle() + "-fx-alignment: CENTER_LEFT;");
    }
};
final TableCell cell=new TableCell(){
自有品牌;
专用窗格;
{
//这是匿名类的构造函数。或者,您可以选择在第一次需要标签和窗格时延迟创建它们。
标签=新标签();
窗格=新的堆叠窗格(标签);
窗格设置对齐(位置中心);
标签。设置最大宽度(10);
标签设置最小宽度(10);
标签设置最小高度(30);
}
@凌驾
public void updateItem(访问项,布尔值为空){
super.updateItem(项,空);
if(空| | getIndex()<0){
设置图形(空);
setText(空);
返回;
}
item=getTableView().getItems().get(getIndex());
setText(item.getStatus().display());
String background=fxmlstants.toHexString(ColorUtils.getVisitBackgroundColor(item));
pane.setStyle(String.format(“-fx背景色:%s;;”,背景));
设置图形(窗格);
setText(item.getStatus().display());
setStyle(getStyle()+“-fx对齐:中间左;”;
}
};

另外-如果您从未设置标签的文本,标签有什么用途?单元格的
contentDisplay
是什么?是否显示了节点

这在很大程度上取决于表中行的数据类型以及显示它们的方式(自定义单元格工厂)。如果没有更多的上下文(即-用作数据模型的类和表上使用的任何单元格工厂),几乎无法判断它是否正常。@sillyfly请检查更新,我添加了一个我如何创建表列的示例您的解决方案确实解决了问题,,使用了标签,然后我设置了单元格文本[标签将被删除]、、一个问题