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

Memory leak when using WebView with Tooltip

XMLWordPrintable

    • web
    • generic
    • generic

      FULL PRODUCT VERSION :
      java version "1.8.0_151"
      Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
      Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      We embbed a WebView into a JFXPanel. If the web page which is shown by the WebView contains elements with tooltips, e.g. a button, and the tooltip is shown, then the WebView is not garbage collected even if the surrounding frame is disposed. There seems to be still a reference to the tooltip component via the com.sun.webkit.WebPage instance.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Use the source code below.

      We open a frame with a JFXPanel that contains a WebView. The WebView shows a page with a button with a tooltip. Do the following steps:
       - start the application with the VM-argument "-DUSE_CLEANUP_WORKAROUND=false"
       - click on "Open new browser window"
       - hover over the upcoming button "Show my tooltip" until the tooltip is shown
       - close the web view frame
       

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      After closeing the frame of the JXFPanel all WebView instance are garbage collected.
      ACTUAL -
       If you use a profiler you'll see that the WebView is not garbage collected since it is still referenced by the tooltip component which is referenced by an com.sun.webkit.WebPage instance.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      === TooltipTestFXSwing.java ===

      package tooltiptest;

      import java.awt.BorderLayout;
      import java.awt.event.WindowAdapter;
      import java.awt.event.WindowEvent;
      import java.net.URISyntaxException;

      import javax.swing.JButton;
      import javax.swing.JFrame;
      import javax.swing.JPanel;

      import com.sun.javafx.application.PlatformImpl;

      import javafx.application.Platform;
      import javafx.embed.swing.JFXPanel;
      import javafx.scene.Scene;
      import javafx.scene.layout.Region;
      import javafx.scene.web.WebView;

      public class TooltipTestFXSwing
      {

      public static boolean USE_CLEANUP_WORKAROUND = Boolean.getBoolean("USE_CLEANUP_WORKAROUND");


      /**
      * @see javafx.application.Application#start(javafx.stage.Stage)
      */
      public void start()
      {
      JFrame frame = new JFrame("TooltipTestSwing");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      JPanel panel = (JPanel) frame.getContentPane();
      panel.setLayout(new BorderLayout());

      JButton btn = new JButton("Open new browser window");
      btn.addActionListener(e -> reloadPage());
      panel.add(btn, BorderLayout.NORTH);

      frame.pack();
      frame.setVisible(true);

      PlatformImpl.startup(() -> System.out.println("init"));
      }

      public void reloadPage()
      {
      JFrame frame = new JFrame("TooltipTestSwing");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

      JPanel panel = (JPanel) frame.getContentPane();
      panel.setLayout(new BorderLayout());

      JFXPanel jfxPanel = new JFXPanel();
      panel.add(jfxPanel, BorderLayout.CENTER);

      frame.setSize(800, 600);
      frame.setVisible(true);

      Platform.setImplicitExit(false);
      Platform.runLater(() ->
      {
      WebView webView = new WebView();
      try
      {
      webView.getEngine().load(TooltipTestFXSwing.class.getResource("tooltip.html").toURI().toString());
      }
      catch (URISyntaxException e1)
      {
      e1.printStackTrace();
      }

      Scene scene = new Scene(webView, 800, 600);
      jfxPanel.setScene(scene);
      });

      frame.addWindowListener(new WindowAdapter()
      {
      @Override
      public void windowClosing(WindowEvent e)
      {
      if (USE_CLEANUP_WORKAROUND)
      {
      Platform.runLater(() -> jfxPanel.setScene(new Scene(new Region())));
      frame.removeAll();
      }
      frame.dispose();
      }
      });
      }

      public static void main(String[] args)
      {
      new TooltipTestFXSwing().start();
      }
      }

      === tooltip.html ===
      <!DOCTYPE html>
      <html>
      <head>
      </head>
      <body>
      <form>
      <button title="Tooltip" type="button">Show my tooltip</button>
      </form>
      </body>
      </html>

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

      CUSTOMER SUBMITTED WORKAROUND :
      Before disposeing the frame call this:

      Platform.runLater(() -> jfxPanel.setScene(new Scene(new Region())));
      frame.removeAll();

        1. TooltipTestFXSwing.java
          2 kB
        2. TooltipTestFXSwing.java
          3 kB
        3. TooltipTestFX.java
          2 kB
        4. Tooltip.png
          Tooltip.png
          48 kB
        5. tooltip.html
          0.2 kB

            mbilla Murali Billa
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: