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

Memory leak in com.apple.laf.ScreenMenu: removed JMenuItems are still referenced

    Details

    • Subcomponent:
    • Resolved In Build:
      b127
    • CPU:
      x86
    • OS:
      other

      Backports

        Description

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

        ADDITIONAL OS VERSION INFORMATION :
        Darwin saotome.local 15.4.0 Darwin Kernel Version 15.4.0: Fri Feb 26 22:08:05 PST 2016; root:xnu-3248.40.184~3/RELEASE_X86_64 x86_64

        A DESCRIPTION OF THE PROBLEM :
        When using the system menu bar on OS X (System.setProperty("apple.laf.useScreenMenuBar", "true")), any JMenuItem you remove from a JMenu is still referenced as long as the menu bar exists.

        The problem is located in the ScreenMenu class:

        1) The ScreenMenu class attaches a ContainerListener to the invoker (=the JMenu instance) in the addNotify method . However, the JMenu never fires ContainerEvents. It is the JMenu#getPopupMenu that fires the events. As such, the cleanup code in com.apple.laf.ScreenMenu#componentRemoved is never triggered

        2) In the com.apple.laf.ScreenMenu#componentRemoved, the entry from fItems is never removed, because the remove method is called with the value instead of the key

        3) The com.apple.laf.ScreenMenu#updateItems method removes all entries through a removeAll call, but does not remove those entries from the fItems map (nor does it always clean the childHashArray, but that is no memory leak)

        The attached test program illustrates that the JMenuItem, which has been removed from the JMenuBar, is still referenced.

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Run the attached program

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Expected result is a successful termination of the program
        ACTUAL -
        A RuntimeException is thrown, because the JMenuItem is still referenced.

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        import java.awt.EventQueue;
        import java.lang.ref.WeakReference;
        import java.lang.reflect.InvocationTargetException;
        import java.util.Objects;

        import javax.swing.JFrame;
        import javax.swing.JLabel;
        import javax.swing.JMenu;
        import javax.swing.JMenuBar;
        import javax.swing.JMenuItem;
        import javax.swing.WindowConstants;

        public class MenuBarMemoryLeakTest {
          private static byte[] sBytes;

          private static WeakReference<JMenuItem> sMenuItem;
          private static JFrame sFrame;
          private static JMenu sMenu;

          public static void main(String[] args) throws InvocationTargetException, InterruptedException {
            EventQueue.invokeAndWait(new Runnable() {
              @Override
              public void run() {
                System.setProperty("apple.laf.useScreenMenuBar", "true");
                showUI();
              }
            });

            EventQueue.invokeAndWait(new Runnable() {
              @Override
              public void run() {
                removeMenuItemFromMenu();
              }
            });
            fillUpMemory();
            JMenuItem menuItem = sMenuItem.get();
            EventQueue.invokeAndWait(new Runnable() {
              @Override
              public void run() {
                sFrame.dispose();
              }
            });
            if ( menuItem != null ){
              throw new RuntimeException("The menu item should have been GC-ed");
            }
          }

          private static void showUI(){
            sFrame = new JFrame();
            sFrame.add(new JLabel("Some dummy content"));

            JMenuBar menuBar = new JMenuBar();

            sMenu = new JMenu("Menu");
            JMenuItem item = new JMenuItem("Item");
            sMenu.add(item);

            sMenuItem = new WeakReference<>(item);

            menuBar.add(sMenu);

            sFrame.setJMenuBar(menuBar);
            sFrame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
            sFrame.pack();
            sFrame.setVisible(true);
          }

          private static void removeMenuItemFromMenu(){
            JMenuItem menuItem = sMenuItem.get();
            Objects.requireNonNull(menuItem,"The menu item should still be available at this point");
            sMenu.remove(menuItem);
          }

          /**
           * Fill up the available heap space to ensure that any Soft and WeakReferences gets cleaned up
           */
          private static void fillUpMemory(){
            int size = 1000000;
            for (int i = 0; i < 50; i++) {
              System.gc();
              System.runFinalization();
              try {
                sBytes = null;
                sBytes = new byte[size];
                size = (int) (((double) size) * 1.3);
              } catch (OutOfMemoryError error) {
                size = size / 2;
              }
              try {
                if (i % 3 == 0) {
                  Thread.sleep(321);
                }
              } catch (InterruptedException t) {
                // ignore
              }
            }
            sBytes = null;
          }
        }

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

        CUSTOMER SUBMITTED WORKAROUND :
        Workaround is not using the system menu bar.

          Activity

          webbuggrp Webbug Group created issue -
          aroy Abhijit Roy (Inactive) made changes -
          Field Original Value New Value
          Labels webbug dcsroy reproducer-yes webbug
          aroy Abhijit Roy (Inactive) made changes -
          Project Java Incidents [ 10301 ] JDK [ 10100 ]
          Key JI-9038899 JDK-8158325
          Workflow JBS Incident Workflow [ 4895185 ] JBS Workflow [ 4895185 ]
          Component/s client-libs [ 10307 ]
          Component/s client-libs [ 10700 ]
          Affects Version/s 8u92 [ 18505 ]
          Affects Version/s 8u92 [ 18546 ]
          aroy Abhijit Roy (Inactive) made changes -
          Subcomponent javax.swing [ 490 ] javax.swing [ 206 ]
          vdyakov Victor Dyakov made changes -
          Assignee Alexander Zvegintsev [ azvegint ]
          azvegint Alexander Zvegintsev (Inactive) made changes -
          Status New [ 10000 ] Open [ 1 ]
          azvegint Alexander Zvegintsev (Inactive) made changes -
          Fix Version/s 9 [ 14949 ]
          vdyakov Victor Dyakov made changes -
          Affects Version/s 9 [ 14949 ]
          vdyakov Victor Dyakov made changes -
          Priority P4 [ 4 ] P3 [ 3 ]
          Show
          alexsch Alexander Scherbatiy (Inactive) added a comment - The proposed fix: http://cr.openjdk.java.net/~alexsch/robin.stevens/8158325/webrev.00 See discussion: http://mail.openjdk.java.net/pipermail/swing-dev/2016-June/006200.html
          Hide
          hgupdate HG Updates added a comment -
          URL: http://hg.openjdk.java.net/jdk9/client/jdk/rev/3bcead661fa6
          User: alexsch
          Date: 2016-06-30 16:07:49 +0000
          Show
          hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/client/jdk/rev/3bcead661fa6 User: alexsch Date: 2016-06-30 16:07:49 +0000
          hgupdate HG Updates made changes -
          Status Open [ 1 ] Resolved [ 5 ]
          Resolved In Build team [ 17324 ]
          Resolution Fixed [ 1 ]
          Hide
          hgupdate HG Updates added a comment -
          URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/3bcead661fa6
          User: amurillo
          Date: 2016-07-13 03:50:56 +0000
          Show
          hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/3bcead661fa6 User: amurillo Date: 2016-07-13 03:50:56 +0000
          hgupdate HG Updates made changes -
          Resolved In Build team [ 17324 ] master [ 18256 ]
          hgupdate HG Updates made changes -
          Resolved In Build master [ 18256 ] b127 [ 17762 ]
          hgupdate HG Updates made changes -
          Link This issue backported by JDK-8161498 [ JDK-8161498 ]
          hgupdate HG Updates made changes -
          Link This issue backported by JDK-8183699 [ JDK-8183699 ]
          hgupdate HG Updates made changes -
          Link This issue backported by JDK-8192435 [ JDK-8192435 ]

            People

            • Assignee:
              azvegint Alexander Zvegintsev (Inactive)
              Reporter:
              webbuggrp Webbug Group
            • Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: