-
Bug
-
Resolution: Unresolved
-
P3
-
jfx11, 8, 9, 10
-
x86_64
-
generic
FULL PRODUCT VERSION :
java version "1.8.0_162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Windows 10.0.16299.309
A DESCRIPTION OF THE PROBLEM :
Load a large image, set it into an ImageView node, set the image of this ImageView node to null, then remove this ImageView node from scene graph.
The large image object does not get garbage collected.
If the ImageView node was not removed from scene graph after set it's image to null, the image object can be garbage collected.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the test application with vm param -Xmx768m.
Click "New Stage" button
Click "Hide Image" button on the new stage, do not close the new stage.
Repeat last two steps several times, OutOfMemoryError will occur.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ImageMemTest extends Application {
public static void main(String[] args) {
launch(ImageMemTest.class, args);
}
@Override
public void start(Stage primaryStage) throws Exception {
Button openStageBtn = new Button("New Stage");
openStageBtn.setOnAction(e -> {
Stage newStage = new Stage();
VBox root = new VBox(10);
ScrollPane scrollPane = new ScrollPane(new ImageView(new WritableImage(5000, 5000)));
scrollPane.setPrefWidth(500);
scrollPane.setPrefHeight(500);
Button hideImgBtn = new Button("Hide Image");
hideImgBtn.setOnAction(evt -> {
if (scrollPane.getContent() instanceof ImageView) {
ImageView imgView = (ImageView) scrollPane.getContent();
imgView.setImage(null);
scrollPane.setContent(new Label());
// uncomment these three lines, the OutOfMemoryError will not occur.
// root.getChildren().add(imgView);
// imgView.setVisible(false);
// imgView.setManaged(false);
}
});
root.getChildren().addAll(scrollPane, hideImgBtn);
root.setStyle("-fx-padding: 10px");
newStage.setScene(new Scene(root));
newStage.show();
});
HBox btnBox = new HBox(10, openStageBtn);
primaryStage.setScene(new Scene(btnBox));
btnBox.setStyle("-fx-padding: 100px");
primaryStage.show();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Hide the ImageView node somewhere in scene graph after set image to null.
Do not from the ImageView node from scene graph.
java version "1.8.0_162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Windows 10.0.16299.309
A DESCRIPTION OF THE PROBLEM :
Load a large image, set it into an ImageView node, set the image of this ImageView node to null, then remove this ImageView node from scene graph.
The large image object does not get garbage collected.
If the ImageView node was not removed from scene graph after set it's image to null, the image object can be garbage collected.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the test application with vm param -Xmx768m.
Click "New Stage" button
Click "Hide Image" button on the new stage, do not close the new stage.
Repeat last two steps several times, OutOfMemoryError will occur.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ImageMemTest extends Application {
public static void main(String[] args) {
launch(ImageMemTest.class, args);
}
@Override
public void start(Stage primaryStage) throws Exception {
Button openStageBtn = new Button("New Stage");
openStageBtn.setOnAction(e -> {
Stage newStage = new Stage();
VBox root = new VBox(10);
ScrollPane scrollPane = new ScrollPane(new ImageView(new WritableImage(5000, 5000)));
scrollPane.setPrefWidth(500);
scrollPane.setPrefHeight(500);
Button hideImgBtn = new Button("Hide Image");
hideImgBtn.setOnAction(evt -> {
if (scrollPane.getContent() instanceof ImageView) {
ImageView imgView = (ImageView) scrollPane.getContent();
imgView.setImage(null);
scrollPane.setContent(new Label());
// uncomment these three lines, the OutOfMemoryError will not occur.
// root.getChildren().add(imgView);
// imgView.setVisible(false);
// imgView.setManaged(false);
}
});
root.getChildren().addAll(scrollPane, hideImgBtn);
root.setStyle("-fx-padding: 10px");
newStage.setScene(new Scene(root));
newStage.show();
});
HBox btnBox = new HBox(10, openStageBtn);
primaryStage.setScene(new Scene(btnBox));
btnBox.setStyle("-fx-padding: 100px");
primaryStage.show();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Hide the ImageView node somewhere in scene graph after set image to null.
Do not from the ImageView node from scene graph.