Проблемы с памятью 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.,