Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8123079

Timeline prevents objects that are animated to be gc'ed

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • 8
    • 8
    • javafx

      From John Hendrikx's mail:

      I'm having trouble creating a reproducable test case.

      There seems to be more going on -- if I open and close the Pane involved several times, eventually some of them will start to be GC'd (but never all, unless I disable the animation). I've used VisualVM to inspect the Pane involved, and here is what it says is keeping it alive (clearly something animation related atleast):

      this - value: hs.mediasystem.screens.playback.PlaybackOverlayPane #1
      <- this$0 - class: javafx.scene.Node$8, value: hs.mediasystem.screens.playback.PlaybackOverlayPane #1
      <- target - class: com.sun.scenario.animation.shared.InterpolationInterval$DoubleInterpolationInterval, value: javafx.scene.Node$8 #149
      <- [0] - class: com.sun.scenario.animation.shared.InterpolationInterval[], value: com.sun.scenario.animation.shared.InterpolationInterval$DoubleInterpolationInterval #28
      <- [0] - class: com.sun.scenario.animation.shared.InterpolationInterval[][], value: com.sun.scenario.animation.shared.InterpolationInterval[] #10 (3 items)
      <- interval - class: com.sun.scenario.animation.shared.GeneralClipInterpolator, value: com.sun.scenario.animation.shared.InterpolationInterval[][] #16 (1 items)
      <- clipInterpolator - class: com.sun.scenario.animation.shared.TimelineClipCore, value: com.sun.scenario.animation.shared.GeneralClipInterpolator #16
      <- clipCore - class: javafx.animation.Timeline, value: com.sun.scenario.animation.shared.TimelineClipCore #19
      <- this$0 - class: javafx.animation.Animation$1, value: javafx.animation.Timeline #19
      <- [5] - class: com.sun.scenario.animation.shared.PulseReceiver[], value: javafx.animation.Animation$1 #19
      <- receivers - class: com.sun.javafx.tk.quantum.MasterTimer, value: com.sun.scenario.animation.shared.PulseReceiver[] #1 (7 items)
      <- this$0 - class: com.sun.scenario.animation.AbstractMasterTimer$MainLoop, value: com.sun.javafx.tk.quantum.MasterTimer #1
      <- animationRunnable - class: com.sun.javafx.tk.quantum.QuantumToolkit, value: com.sun.scenario.animation.AbstractMasterTimer$MainLoop #1
      <- this$0 (JNI global) - class: com.sun.javafx.tk.quantum.QuantumToolkit$14, value: com.sun.javafx.tk.quantum.QuantumToolkit #1

      If that is enough for a bugreport, I'll create one. A naive simple test case which spawns several panes and animations was unable to reproduce this issue I'm having:

      package hs.mediasystem;

      import javafx.animation.KeyFrame;
      import javafx.animation.KeyValue;
      import javafx.animation.Timeline;
      import javafx.application.Application;
      import javafx.application.Platform;
      import javafx.beans.value.ChangeListener;
      import javafx.beans.value.ObservableValue;
      import javafx.beans.value.WeakChangeListener;
      import javafx.scene.Scene;
      import javafx.scene.control.Button;
      import javafx.scene.layout.StackPane;
      import javafx.stage.Stage;
      import javafx.util.Duration;

      public class TimelineGCProblem extends Application {

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

        @Override
        public void start(Stage stage) throws Exception {
          StackPane rootPane = new StackPane();
          Scene scene = new Scene(rootPane);

          stage.setScene(scene);
          stage.show();

          new Thread() {
            @Override
            public void run() {
              for(;;) {
                Platform.runLater(new Runnable() {
                  @Override
                  public void run() {
                    rootPane.getChildren().setAll(new FadeInPane());
                  }
                });

                try {
                  System.gc();
                  Thread.sleep(1500);
                  System.gc();
                }
                catch(InterruptedException e) {
                  e.printStackTrace();
                }
              }
            }

          }.start();
        }

        public static class FadeInPane extends StackPane {
          private final Timeline fadeInSustainAndFadeOut = new Timeline(
            new KeyFrame(Duration.seconds(0)),
            new KeyFrame(Duration.seconds(1), new KeyValue(opacityProperty(), 1.0)),
            new KeyFrame(Duration.seconds(6), new KeyValue(opacityProperty(), 1.0)),
            new KeyFrame(Duration.seconds(8), new KeyValue(opacityProperty(), 0.0))
          );

          private final ChangeListener<Scene> sceneChangeListener = new ChangeListener<Scene>() {
            @Override
            public void changed(ObservableValue<? extends Scene> observable, Scene oldValue, Scene newValue) {
              if(newValue != null) {
                System.out.println(">>> Starting fadeIn anim");
                fadeInSustainAndFadeOut.playFromStart();
              }
              else {
                System.out.println(">>> Stopping fadeIn anim");
                fadeInSustainAndFadeOut.stop();
              }
            }
          };

          public FadeInPane() {
            sceneProperty().addListener(new WeakChangeListener<>(sceneChangeListener));

            setStyle("background-color: red");
            getChildren().add(new Button("Hi"));
          }

          @Override
          protected void finalize() throws Throwable {
            super.finalize();
            System.out.println("FadeInPane finalized");
          }
        }
      }

            msladecek Martin Sládeček
            msladecek Martin Sládeček
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported: