changeset 16325:fc6ede6780e5

8165769: Hang in the help menu item Reviewed-by: alexsch, aivanov
author serb
date Thu, 08 Dec 2016 08:11:47 -0800
parents a21bac70753d
children d8efcad28072
files src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java src/java.desktop/share/classes/java/awt/Menu.java src/java.desktop/share/classes/java/awt/MenuBar.java src/java.desktop/share/classes/java/awt/MenuComponent.java src/java.desktop/share/classes/java/awt/MenuItem.java src/java.desktop/share/classes/java/awt/PopupMenu.java test/java/awt/Menu/WrongParentAfterRemoveMenu/WrongParentAfterRemoveMenu.java
diffstat 7 files changed, 218 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java	Wed Dec 07 15:52:33 2016 -0800
+++ b/src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java	Thu Dec 08 08:11:47 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,18 +22,25 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.awt;
 
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
 import java.awt.peer.CheckboxMenuItemPeer;
-import java.awt.event.*;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 import java.util.EventListener;
-import java.io.ObjectOutputStream;
-import java.io.ObjectInputStream;
-import java.io.IOException;
-import javax.accessibility.*;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleAction;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleValue;
+
 import sun.awt.AWTAccessor;
 
-
 /**
  * This class represents a check box that can be included in a menu.
  * Selecting the check box in the menu changes its state from
@@ -43,7 +50,8 @@
  * of {@code CheckBoxMenuItem}:
  * <p>
  * <img src="doc-files/MenuBar-1.gif"
- * alt="Menu labeled Examples, containing items Basic, Simple, Check, and More Examples. The Check item is a CheckBoxMenuItem instance, in the off state."
+ * alt="Menu labeled Examples, containing items Basic, Simple, Check, and More
+ * Examples. The Check item is a CheckBoxMenuItem instance, in the off state."
  * style="float:center; margin: 7px 10px;">
  * <p>
  * The item labeled {@code Check} shows a check box menu item
@@ -84,9 +92,9 @@
     * @see #getState()
     * @see #setState(boolean)
     */
-    boolean state = false;
+    private volatile boolean state;
 
-    transient ItemListener itemListener;
+    private transient volatile ItemListener itemListener;
 
     private static final String base = "chkmenuitem";
     private static int nameCounter = 0;
--- a/src/java.desktop/share/classes/java/awt/Menu.java	Wed Dec 07 15:52:33 2016 -0800
+++ b/src/java.desktop/share/classes/java/awt/Menu.java	Thu Dec 08 08:11:47 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,15 +22,20 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.awt;
 
+import java.awt.event.KeyEvent;
+import java.awt.peer.MenuPeer;
 import java.io.IOException;
 import java.io.ObjectInputStream;
+import java.util.Enumeration;
 import java.util.Vector;
-import java.util.Enumeration;
-import java.awt.peer.MenuPeer;
-import java.awt.event.KeyEvent;
-import javax.accessibility.*;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+
 import sun.awt.AWTAccessor;
 
 /**
@@ -78,7 +83,7 @@
      * @serial
      * @see #countItems()
      */
-    Vector<MenuItem> items = new Vector<>();
+    private final Vector<MenuItem> items = new Vector<>();
 
     /**
      * This field indicates whether the menu has the
@@ -92,7 +97,7 @@
      * @serial
      * @see #isTearOff()
      */
-    boolean             tearOff;
+    private final boolean tearOff;
 
     /**
      * This field will be set to {@code true}
@@ -102,7 +107,7 @@
      *
      * @serial
      */
-    boolean             isHelpMenu;
+    volatile boolean isHelpMenu;
 
     private static final String base = "menu";
     private static int nameCounter = 0;
@@ -415,8 +420,8 @@
             if (peer != null) {
                 peer.delItem(index);
                 mi.removeNotify();
-                mi.parent = null;
             }
+            mi.parent = null;
         }
     }
 
--- a/src/java.desktop/share/classes/java/awt/MenuBar.java	Wed Dec 07 15:52:33 2016 -0800
+++ b/src/java.desktop/share/classes/java/awt/MenuBar.java	Thu Dec 08 08:11:47 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,16 +22,21 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.awt;
 
+import java.awt.event.KeyEvent;
+import java.awt.peer.MenuBarPeer;
 import java.io.IOException;
 import java.io.ObjectInputStream;
+import java.util.Enumeration;
 import java.util.Vector;
-import java.util.Enumeration;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+
 import sun.awt.AWTAccessor;
-import java.awt.peer.MenuBarPeer;
-import java.awt.event.KeyEvent;
-import javax.accessibility.*;
 
 /**
  * The {@code MenuBar} class encapsulates the platform's
@@ -94,7 +99,7 @@
      * @serial
      * @see #countMenus()
      */
-    Vector<Menu> menus = new Vector<>();
+    private final Vector<Menu> menus = new Vector<>();
 
     /**
      * This menu is a special menu dedicated to
@@ -106,7 +111,7 @@
      * @see #getHelpMenu()
      * @see #setHelpMenu(Menu)
      */
-    Menu helpMenu;
+    private volatile Menu helpMenu;
 
     private static final String base = "menubar";
     private static int nameCounter = 0;
@@ -252,8 +257,8 @@
             if (peer != null) {
                 peer.delMenu(index);
                 m.removeNotify();
-                m.parent = null;
             }
+            m.parent = null;
             if (helpMenu == m) {
                 helpMenu = null;
                 m.isHelpMenu = false;
--- a/src/java.desktop/share/classes/java/awt/MenuComponent.java	Wed Dec 07 15:52:33 2016 -0800
+++ b/src/java.desktop/share/classes/java/awt/MenuComponent.java	Thu Dec 08 08:11:47 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,21 +22,28 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.awt;
 
+import java.awt.event.ActionEvent;
 import java.awt.peer.MenuComponentPeer;
-import java.awt.event.ActionEvent;
 import java.io.IOException;
 import java.io.ObjectInputStream;
-import sun.awt.AppContext;
-import sun.awt.AWTAccessor;
-import sun.awt.ComponentFactory;
-
-import javax.accessibility.*;
-
 import java.security.AccessControlContext;
 import java.security.AccessController;
 
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleComponent;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleSelection;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+
+import sun.awt.AWTAccessor;
+import sun.awt.AppContext;
+import sun.awt.ComponentFactory;
+
 /**
  * The abstract class {@code MenuComponent} is the superclass
  * of all menu-related components. In this respect, the class
@@ -60,13 +67,13 @@
     }
 
     transient volatile MenuComponentPeer peer;
-    transient MenuContainer parent;
+    transient volatile MenuContainer parent;
 
     /**
      * The {@code AppContext} of the {@code MenuComponent}.
      * This is set in the constructor and never changes.
      */
-    transient AppContext appContext;
+    private transient volatile AppContext appContext;
 
     /**
      * The menu component's font. This value can be
@@ -77,7 +84,7 @@
      * @see #setFont(Font)
      * @see #getFont()
      */
-    volatile Font font;
+    private volatile Font font;
 
     /**
      * The menu component's name, which defaults to {@code null}.
@@ -85,7 +92,7 @@
      * @see #getName()
      * @see #setName(String)
      */
-    private String name;
+    private volatile String name;
 
     /**
      * A variable to indicate whether a name is explicitly set.
@@ -94,14 +101,14 @@
      * @serial
      * @see #setName(String)
      */
-    private boolean nameExplicitlySet = false;
+    private volatile boolean nameExplicitlySet;
 
     /**
      * Defaults to {@code false}.
      * @serial
      * @see #dispatchEvent(AWTEvent)
      */
-    boolean newEventsOnly = false;
+    volatile boolean newEventsOnly;
 
     /*
      * The menu's AccessControlContext.
--- a/src/java.desktop/share/classes/java/awt/MenuItem.java	Wed Dec 07 15:52:33 2016 -0800
+++ b/src/java.desktop/share/classes/java/awt/MenuItem.java	Thu Dec 08 08:11:47 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,15 +22,25 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.awt;
 
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
 import java.awt.peer.MenuItemPeer;
-import java.awt.event.*;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 import java.util.EventListener;
-import java.io.ObjectOutputStream;
-import java.io.ObjectInputStream;
-import java.io.IOException;
-import javax.accessibility.*;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleAction;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleValue;
+
 import sun.awt.AWTAccessor;
 
 /**
@@ -111,7 +121,7 @@
      * @see #isEnabled()
      * @see #setEnabled(boolean)
      */
-    boolean enabled = true;
+    private volatile boolean enabled = true;
 
     /**
      * {@code label} is the label of a menu item.
@@ -121,7 +131,7 @@
      * @see #getLabel()
      * @see #setLabel(String)
      */
-    String label;
+    volatile String label;
 
     /**
      * This field indicates the command that has been issued
@@ -134,7 +144,7 @@
      * @see #setActionCommand(String)
      * @see #getActionCommand()
      */
-    String actionCommand;
+    private volatile String actionCommand;
 
     /**
      * The eventMask is ONLY set by subclasses via enableEvents.
@@ -144,9 +154,9 @@
      *
      * @serial
      */
-    long eventMask;
+    volatile long eventMask;
 
-    transient ActionListener actionListener;
+    private transient volatile ActionListener actionListener;
 
     /**
      * A sequence of key stokes that ia associated with
@@ -160,7 +170,7 @@
      * @see #setShortcut(MenuShortcut)
      * @see #deleteShortcut()
      */
-    private MenuShortcut shortcut = null;
+    private volatile MenuShortcut shortcut;
 
     private static final String base = "menuitem";
     private static int nameCounter = 0;
--- a/src/java.desktop/share/classes/java/awt/PopupMenu.java	Wed Dec 07 15:52:33 2016 -0800
+++ b/src/java.desktop/share/classes/java/awt/PopupMenu.java	Thu Dec 08 08:11:47 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,8 +26,9 @@
 package java.awt;
 
 import java.awt.peer.PopupMenuPeer;
-import javax.accessibility.*;
 
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
 
 import sun.awt.AWTAccessor;
 
@@ -48,7 +49,7 @@
     private static final String base = "popup";
     static int nameCounter = 0;
 
-    transient boolean isTrayIconPopup = false;
+    transient volatile boolean isTrayIconPopup;
 
     static {
         AWTAccessor.setPopupMenuAccessor(
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/Menu/WrongParentAfterRemoveMenu/WrongParentAfterRemoveMenu.java	Thu Dec 08 08:11:47 2016 -0800
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.Frame;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.PopupMenu;
+import java.awt.Window;
+
+/**
+ * @test
+ * @bug 8165769
+ * @key headful
+ */
+public final class WrongParentAfterRemoveMenu {
+
+    public static void main(final String[] args) {
+        testMenuBar();
+        testComponent();
+        testFrame();
+    }
+
+    private static void testFrame() {
+        // peer exists
+        Frame frame = new Frame();
+        try {
+            frame.pack();
+            PopupMenu popupMenu = new PopupMenu();
+            frame.add(popupMenu);
+            checkParent(popupMenu, frame);
+            frame.remove(popupMenu);
+            checkParent(popupMenu, null);
+        } finally {
+            frame.dispose();
+        }
+        // peer is null
+        frame = new Frame();
+        PopupMenu popupMenu = new PopupMenu();
+        frame.add(popupMenu);
+        checkParent(popupMenu, frame);
+        frame.remove(popupMenu);
+        checkParent(popupMenu, null);
+    }
+
+    private static void testComponent() {
+        // peer exists
+        Window w = new Window(null);
+        try {
+            w.pack();
+            PopupMenu popupMenu = new PopupMenu();
+            w.add(popupMenu);
+            checkParent(popupMenu, w);
+            w.remove(popupMenu);
+            checkParent(popupMenu, null);
+        } finally {
+            w.dispose();
+        }
+        // peer is null
+        w = new Window(null);
+        PopupMenu popupMenu = new PopupMenu();
+        w.add(popupMenu);
+        checkParent(popupMenu, w);
+        w.remove(popupMenu);
+        checkParent(popupMenu, null);
+    }
+
+    private static void testMenuBar() {
+        // peer exists
+        MenuBar mb = new MenuBar();
+        try {
+            mb.addNotify();
+            Menu m1 = new Menu();
+            Menu m2 = new Menu();
+            m1.add(m2);
+            mb.add(m1);
+            checkParent(m1, mb);
+            checkParent(m2, m1);
+            m1.remove(m2);
+            checkParent(m2, null);
+            mb.remove(m1);
+            checkParent(m1, null);
+        } finally {
+            mb.removeNotify();
+        }
+        // peer is null
+        mb = new MenuBar();
+        Menu m1 = new Menu();
+        Menu m2 = new Menu();
+        m1.add(m2);
+        mb.add(m1);
+        checkParent(m1, mb);
+        checkParent(m2, m1);
+        m1.remove(m2);
+        checkParent(m2, null);
+        mb.remove(m1);
+        checkParent(m1, null);
+    }
+
+    private static void checkParent(final Menu menu, final Object parent) {
+        if (menu.getParent() != parent) {
+            System.err.println("Expected: " + parent);
+            System.err.println("Actual: " + menu.getParent());
+            throw new RuntimeException("Wrong parent");
+        }
+    }
+}