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

Memory leak when switching ButtonSkin

    Details

    • Subcomponent:
    • Understanding:
      Cause Known
    • CPU:
      x86_64
    • OS:
      windows_7

      Description

      ADDITIONAL SYSTEM INFORMATION :
      * OpenJDK 11.0.2
      * Redhat 6.8 and Windows 7 64bit. Confident this is agnostic of OS

      A DESCRIPTION OF THE PROBLEM :
      When the skin of a control is changed the old skin is not garbage collected.

      I've traced this to strong reference in an event listener

      Specifically com.sun.javafx.scene.control.skin.BehaviorSkinBase adds a listener for context menu request in its constructor. i.e. this line

      control.addEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, contextMenuHandler);

      However this listener is never removed in dispose()

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the test application
      Monitor number of skin instances with JVisualVM or other profiler

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Only single instance of skin object, unused instances should be garbage collected
      ACTUAL -
      Constant increase in number of skin objects (i.e. they're not being garbage collected)

      ---------- BEGIN SOURCE ----------
      import com.sun.javafx.scene.control.skin.ButtonSkin;

      import javafx.animation.Animation;
      import javafx.animation.KeyFrame;
      import javafx.animation.Timeline;
      import javafx.application.Application;
      import javafx.scene.Scene;
      import javafx.scene.control.Button;
      import javafx.stage.Stage;
      import javafx.util.Duration;

      public class SkinMemoryLeak extends Application {

          public static class ButtonSkinCustom1 extends ButtonSkin {
              public ButtonSkinCustom1(Button button) {
                  super(button);
              }
          }

          public static class ButtonSkinCustom2 extends ButtonSkin {
              public ButtonSkinCustom2(Button button) {
                  super(button);
              }
          }

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

          @Override
          public void start(Stage primaryStage) throws Exception {
              Button button = new Button("Foo");
              Scene scene = new Scene(button);
              primaryStage.setScene(scene);
              primaryStage.show();
              Timeline animation = new Timeline();
              animation.getKeyFrames().add(new KeyFrame(Duration.seconds(1), event -> {
                  if (button.getSkin() instanceof ButtonSkinCustom2) {
                      button.setSkin(new ButtonSkinCustom1(button));
                  } else {
                      button.setSkin(new ButtonSkinCustom2(button));
                  }
              }));
              animation.setCycleCount(Animation.INDEFINITE);
              animation.play();
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Can be monkey patched by following in affected skin

      @Override
      public void dispose() {
          try {
              Field field = BehaviorSkinBase.class.getDeclaredField("contextMenuHandler");
              field.setAccessible(true);
              EventHandler handler = (EventHandler) field.get(this);
              getSkinnable().removeEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, handler);
          } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
              e.printStackTrace();
          }
          super.dispose();
      }

      FREQUENCY : always


        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                arapte Ambarish Rapte
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated: