JDK-8163079 : Memory leak in JavaFX with software rendering pipeline
  • Type: Bug
  • Component: javafx
  • Sub-Component: graphics
  • Affected Version: 8,9
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • OS: other
  • CPU: x86
  • Submitted: 2016-08-01
  • Updated: 2018-09-05
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :


ADDITIONAL OS VERSION INFORMATION :
Windows (multiple)
Linux

EXTRA RELEVANT SYSTEM CONFIGURATION :
Tested with multiple JDK8 versions in 64 bit.

A DESCRIPTION OF THE PROBLEM :
There happens to be a memory leak when using JavaFX in combination with the software rendering pipeline (-Dprism.order=sw). The leak does NOT occur when using hardware rendering (-Dprism.order=d3d).

Our analysis came to the result that the cause of this memory leak seems to be the class JavaSurface. This class gets created by the JavaFX renderer but is not cleaned up. The finalize() method of the class does not get called anytime.

As the class JavaSurface contains an INT buffer which can be bigger than 1 MB, the impacts of this leak are tremendous. Each switch between different views increases the memory usage by about 0.5 MB to 1.5 MB (in our case).




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.ScrollBar;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class LeakProducer extends Application
{
   @Override
   public void start(Stage primaryStage) throws Exception
   {
      final StackPane root = new StackPane();
      final VBox myBox = new VBox();

      Button scrollBarBtn = new Button();
      scrollBarBtn.setText("Scrollbar");
      scrollBarBtn.setOnAction(x -> {
               if (myBox.getChildren().size() > 1) {
                  myBox.getChildren().remove(1);
                  System.gc();
                  System.runFinalization();
                  System.gc();
                  System.runFinalization();
               } else {
                  myBox.getChildren().add(new ScrollBar());
               }
            });

      Scene scene = new Scene(root, 300, 250);

      myBox.getChildren().add(scrollBarBtn);

      root.getChildren().add(myBox);
      primaryStage.setScene(scene);
      primaryStage.show();
   }

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

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Use hardware rendering (d3d) or deprecated j2d pipeline.


Comments
Since the user is seeing this on multiple version of JDK 8u it does not appear to be a regression.
06-08-2016

I should add that the AbstractSurface class reliance on finalize is a bad design. It's quite possible that what the submitter is seeing is not a Java level memory leak, but rather the consequence of relying on finalize to clean up native resources.
06-08-2016

I ran this on JDK 9 and on JDK 8u102 as follows and I see no leak: 1. Launch the program with "java -verbose:gc -Dprism.order=sw -Dprism.verbose=true ..." 2. Repeatedly click on the "Scrollbar button" which will alternately add and remove a scroll bar I watched the memory usage and cannot see a leak.
06-08-2016