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

TabPane/Tab memory leak

    XMLWordPrintable

    Details

    • Subcomponent:
    • Introduced In Build:
      b13
    • Introduced In Version:
    • CPU:
      generic
    • OS:
      generic

      Description

      ADDITIONAL SYSTEM INFORMATION :
      Windows, Linux, JDK 17

      A DESCRIPTION OF THE PROBLEM :
      Memory is not released on tab removal, when the tab has a ContextMenu with MenuItem, that has reference to the tab.
      Works well on javafx version 17-ea+12, but since 17-ea+13 problem exists.
      I think that the problem is in ControlAcceleratorSupport.java. Since this version a listener is always added to the "anchor", which is a TabPane in this case, so removing the tab does not release memory.

       

      REGRESSION : Last worked in version 16

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Result on 17-ea+12. Memory used after the tab is removed should be similar to memory used without the tab.

      without tab - used mem: 20 MB
      with tab, after gc - used mem: 76 MB
      Tab removed
      removed tab, after gc - used mem: 26 MB
      ACTUAL -
      Result on version 18 (same on 17-ea+13):

      without tab - used mem: 16 MB
      with tab, after gc - used mem: 76 MB
      Tab removed
      removed tab, after gc - used mem: 74 MB


      ---------- BEGIN SOURCE ----------
      public class TabsPaneControllerTest extends Application {

      private static final int LARGE_MEM_BYTES = 50_000_000;

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

      @Override
      public void start(Stage primaryStage) {
      TabPane tabPane = new TabPane();

      Scene scene = new Scene(tabPane);
      primaryStage.setScene(scene);
      primaryStage.setMinHeight(300);
      primaryStage.setMinWidth(300);

      primaryStage.show();


      new Thread(() -> {
      runGc();
      printMem("without tab");

      addTab(tabPane);

      runGc();
      printMem("with tab, after gc");

      Platform.runLater(() -> {
      tabPane.getTabs().remove(0);
      System.out.println("Tab removed");
      });

      // wait for tab removal
      while (!tabPane.getTabs().isEmpty()) {
      sleep(500);
      }
      runGc();
      printMem("removed tab, after gc");

      Platform.exit();
      })
      .start();

      }

      public void addTab(TabPane tabPane) {
      Platform.runLater(() -> {
      Tab tab = new Tab("HeavyTab");
      tab.setUserData(new byte[LARGE_MEM_BYTES]);
      tab.setContextMenu(new ContextMenu());

      // reference to tab in MenuItem (onAction)
      MenuItem menuItemWithReferenceToTab = new MenuItem("RenameTabMenuItem");
      menuItemWithReferenceToTab.setOnAction(e -> tab.setText("tab renamed"));
      tab.getContextMenu().getItems().add(menuItemWithReferenceToTab);

      tabPane.getTabs().add(tab);
      });
      }


      public static void runGc() {
      System.gc();
      sleep(2000);
      }

      private static void sleep(int millis) {
      try {
      Thread.sleep(millis);
      } catch (Exception e) {
      e.printStackTrace(); // ignore
      }
      }

      public static void printMem(String message) {
      Runtime runtime = Runtime.getRuntime();
              long totalMemory = runtime.totalMemory() / 1024 / 1024;
              long freeMemory = runtime.freeMemory() / 1024 / 1024;
              System.out.println(message + "\t - used mem: " + (totalMemory - freeMemory) + " MB");
      }

      }
      ---------- END SOURCE ----------

      FREQUENCY : always


        Attachments

          Issue Links

            Activity

              People

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

                Dates

                Created:
                Updated: