【发布时间】:2019-01-05 23:24:28
【问题描述】:
我有一个 javafx 应用程序内存随着时间的推移不断增加。这让我很困惑,因为我认为我的代码中有内存泄漏。 我发现每次更新 tableview 数据时内存都会增加,没有任何新对象只是更新旧数据。
以下代码的目的是重现同样的问题
public class TableViewSample extends Application {
private boolean running = false;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setTitle("Table View Sample");
TableView<Foo> table = new TableView<>();
ObservableList<Foo> data = FXCollections.observableArrayList(
new Foo(0, 0, 0, 0), new Foo(0, 0, 0, 0), new Foo(0, 0, 0, 0),
new Foo(0, 0, 0, 0), new Foo(0, 0, 0, 0), new Foo(0, 0, 0, 0),
new Foo(0, 0, 0, 0), new Foo(0, 0, 0, 0), new Foo(0, 0, 0, 0),
new Foo(0, 0, 0, 0), new Foo(0, 0, 0, 0), new Foo(0, 0, 0, 0),
new Foo(0, 0, 0, 0), new Foo(0, 0, 0, 0), new Foo(0, 0, 0, 0),
new Foo(0, 0, 0, 0), new Foo(0, 0, 0, 0), new Foo(0, 0, 0, 0),
new Foo(0, 0, 0, 0), new Foo(0, 0, 0, 0), new Foo(0, 0, 0, 0),
new Foo(0, 0, 0, 0), new Foo(0, 0, 0, 0), new Foo(0, 0, 0, 0),
new Foo(0, 0, 0, 0), new Foo(0, 0, 0, 0), new Foo(0, 0, 0, 0)
);
Random random = new Random();
TableColumn<Foo, Integer> num1Col = new TableColumn<>("num1");
num1Col.setCellValueFactory(new PropertyValueFactory<>("num1"));
TableColumn<Foo, Integer> num2Col = new TableColumn<>("num2");
num2Col.setCellValueFactory(new PropertyValueFactory<>("num2"));
TableColumn<Foo, Integer> num3Col = new TableColumn<>("num3");
num3Col.setCellValueFactory(new PropertyValueFactory<>("num3"));
TableColumn<Foo, Integer> num4Col = new TableColumn<>("num4");
num4Col.setCellValueFactory(new PropertyValueFactory<>("num4"));
table.setItems(data);
table.getColumns().addAll(num1Col, num2Col, num3Col, num4Col);
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), event -> {
for (Foo foo : data) {
foo.setNum1(random.nextInt(1000));
foo.setNum2(random.nextInt(1000));
foo.setNum3(random.nextInt(1000));
foo.setNum4(random.nextInt(1000));
}
}));
timeline.setCycleCount(Timeline.INDEFINITE);
Button btn = new Button("start");
btn.setOnAction(event -> {
if (running) {
timeline.stop();
running = false;
btn.setText("start");
} else {
timeline.play();
running = true;
btn.setText("stop");
}
event.consume();
});
VBox vbox = new VBox();
vbox.getChildren().addAll(btn, table);
((Group) scene.getRoot()).getChildren().add(vbox);
stage.setScene(scene);
stage.show();
}
public static class Foo {
private SimpleIntegerProperty num1;
private SimpleIntegerProperty num2;
private SimpleIntegerProperty num3;
private SimpleIntegerProperty num4;
public Foo(int num1, int num2, int num3, int num4) {
this.num1 = new SimpleIntegerProperty(num1);
this.num2 = new SimpleIntegerProperty(num2);
this.num3 = new SimpleIntegerProperty(num3);
this.num4 = new SimpleIntegerProperty(num4);
}
public int getNum1() {
return num1.get();
}
public SimpleIntegerProperty num1Property() {
return num1;
}
public void setNum1(int num1) {
this.num1.set(num1);
}
public int getNum2() {
return num2.get();
}
public SimpleIntegerProperty num2Property() {
return num2;
}
public void setNum2(int num2) {
this.num2.set(num2);
}
public int getNum3() {
return num3.get();
}
public SimpleIntegerProperty num3Property() {
return num3;
}
public void setNum3(int num3) {
this.num3.set(num3);
}
public int getNum4() {
return num4.get();
}
public SimpleIntegerProperty num4Property() {
return num4;
}
public void setNum4(int num4) {
this.num4.set(num4);
}
}
}
我做错了什么以及如何解决这种内存增加?
【问题讨论】:
-
您是否通过调试器运行代码以查看内存增加的时间/位置?
-
您收到 OutOfMemoryError 了吗?
-
我猜因为程序似乎每秒创建许多对象(表类可能会为原始 int 值创建 Integer 包装器对象),它们只会填充内存,直到它们被 GC 删除...
-
我尝试运行 gc 并没有删除任何内容,内存不断增加并且永远不会下降,如果我停止更新数据内存停止增加但增加的内存永远不会被删除
-
您检查以确保 GC 确实运行了吗?请求 GC 运行并不能保证它一定会发生。