-
Bug
-
Resolution: Fixed
-
P3
-
8, 9
-
x86
-
os_x
FULL PRODUCT VERSION :
java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
MacOS X El Capitan 10.11.1
A DESCRIPTION OF THE PROBLEM :
The class "Scene" has a field called scrollGesture which keeps a reference to the last target / node that was scrolled. If the target / node gets removed from the scene then it can not be garbage collected.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
- Create a list view with a list of items (e.g. "TestItem").
- Add the view to the scene.
- Scroll the view with a gesture (e.g. swipe down on Mac Magic Mouse)
- Remove the list view from the scene
When using jvisualvm you will see that the last list of TestItems will still be in memory / in the heap.
More details and screenshots on my blog at https://dlemmermann.wordpress.com/2016/01/29/javafx-scrollgesture-memory-leak/
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
All instances of TestItem should have been garbage collected.
ACTUAL -
All instances of TestItem are still there.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
No error log, this needs to be profiled. The heap has to be examined.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class MemoryLeakListViewApp extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
BorderPane pane = new BorderPane();
Scene scene = new Scene(pane);
Button createButton = new Button("Create");
createButton.setOnAction(evt -> {
ListView<TestItem> listView = new ListView<>();
List<TestItem> children = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
children.add(new TestItem("Row " + i));
}
listView.getItems().setAll(children);
pane.setCenter(listView);
});
Button deleteButton = new Button("Destroy");
deleteButton.setOnAction(evt -> {
pane.setCenter(null);
});
HBox box = new HBox();
box.getChildren().addAll(createButton, deleteButton);
pane.setTop(box);
primaryStage.setScene(scene);
primaryStage.setWidth(800);
primaryStage.setHeight(800);
primaryStage.show();
}
static class TestItem {
private String name;
public TestItem(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
public static void main(String[] args) {
launch(args);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
None that I can think of right now.
java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
MacOS X El Capitan 10.11.1
A DESCRIPTION OF THE PROBLEM :
The class "Scene" has a field called scrollGesture which keeps a reference to the last target / node that was scrolled. If the target / node gets removed from the scene then it can not be garbage collected.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
- Create a list view with a list of items (e.g. "TestItem").
- Add the view to the scene.
- Scroll the view with a gesture (e.g. swipe down on Mac Magic Mouse)
- Remove the list view from the scene
When using jvisualvm you will see that the last list of TestItems will still be in memory / in the heap.
More details and screenshots on my blog at https://dlemmermann.wordpress.com/2016/01/29/javafx-scrollgesture-memory-leak/
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
All instances of TestItem should have been garbage collected.
ACTUAL -
All instances of TestItem are still there.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
No error log, this needs to be profiled. The heap has to be examined.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class MemoryLeakListViewApp extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
BorderPane pane = new BorderPane();
Scene scene = new Scene(pane);
Button createButton = new Button("Create");
createButton.setOnAction(evt -> {
ListView<TestItem> listView = new ListView<>();
List<TestItem> children = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
children.add(new TestItem("Row " + i));
}
listView.getItems().setAll(children);
pane.setCenter(listView);
});
Button deleteButton = new Button("Destroy");
deleteButton.setOnAction(evt -> {
pane.setCenter(null);
});
HBox box = new HBox();
box.getChildren().addAll(createButton, deleteButton);
pane.setTop(box);
primaryStage.setScene(scene);
primaryStage.setWidth(800);
primaryStage.setHeight(800);
primaryStage.show();
}
static class TestItem {
private String name;
public TestItem(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
public static void main(String[] args) {
launch(args);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
None that I can think of right now.