Проблемы с памятью Javafx TextField

Я мог бы использовать некоторую помощь для отладки проблемы с памятью (утечка?). Я сделал простой пример ниже. В Javafx есть какая-то ошибка, связанная с TextFields. Приведенный ниже код добавляет 2000 TextFields в FlowPane внутри ScrollPane. Согласно диспетчеру задач, Java использует ~420 МБ на данный момент.

Нажатие кнопки добавления добавляет еще 2000 TextFields при каждом нажатии. Каждый раз добавляет, может быть, 80-200 МБ (как-то это не всегда тот же объем памяти??). Кнопка удаления удаляет TextFields, но память никогда не освобождается. Это с Java jdk 9, где, насколько я понимаю, GC должен освободить память, которая больше не используется, и вернуть ее в ОС. Изменение TextFields на Texts решает проблему, занимает гораздо меньше памяти и фактически возвращает ее в ОС, когда это уместно, но я бы предпочел иметь TextFields. Кто-нибудь знает как это исправить / обойти?:-)

import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Text;
import javafx.stage.Stage;


public class main extends Application
{
    private ScrollPane scroll;
    private FlowPane pane;
    private Scene scene;
    private Stage stage;
    @Override
    public void start(Stage stage) throws Exception
    {
        try
        {
            this.stage=stage;
            pane = new FlowPane();
            Button b1 = new Button("Add 2000");
            Button b = new Button("Remove 2000");

            b1.setOnAction(new EventHandler<ActionEvent>() {

                @Override public void handle(ActionEvent e) {
                    addTextFields();

                }});        
            b.setOnAction(new EventHandler<ActionEvent>() {

                    @Override public void handle(ActionEvent e) {
                        removeTextFields();
                        System.gc();

            }});
            pane.getChildren().add(b);
            pane.getChildren().add(b1);



            scroll = new ScrollPane();



            scroll.setContent(pane);


            addTextFields();

            scene = new Scene(scroll,800,600);

            stage.setScene(scene);
            stage.show();


        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

    }

    private void addTextFields()
    {
        for(int i=0; i < 2000; i++)
        {
            //Text text = new Text("T " + i);
            TextField textField = new TextField("T "+i);

            this.pane.getChildren().add(textField); 
        }
    }

    private void removeTextFields()
    {
        for(int i=2001; i>1; i--)
        {       
        //  Text f = (Text) this.pane.getChildren().get(i);
            TextField f = (TextField) this.pane.getChildren().get(i);

            this.pane.getChildren().remove(f);          
        }

    }

    public static void main(String[] args)
    {
        launch(args);
    }

}

1 ответ

По-видимому, для java 9 вполне нормально, например, продолжать занимать более ГБ в памяти пространства кучи только с базовым этапом, полосой прокрутки и пустой потоковой областью в игре (которая раньше содержала несколько тысяч текстовых полей). Память никогда не высвобождается обратно в ОС, если она не принудительно вызывается в VisualVM даже после явного вызова GC из кода.

Такое поведение GC не имеет никакого смысла для меня, особенно в системе бедняка с только 4 ГБ оперативной памяти, которая уже в основном используется до того, как я запустил Java, но я буду обходить ее, используя Texts или TableView.,

Другие вопросы по тегам