From e8208dd0be70a6debda3cd6218452d660ca8a7af Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Thu, 8 Dec 2016 08:11:47 -0800 Subject: [PATCH] 8165769: Hang in the help menu item Reviewed-by: alexsch, aivanov --- .../classes/java/awt/CheckboxMenuItem.java | 28 ++-- .../share/classes/java/awt/Menu.java | 23 ++-- .../share/classes/java/awt/MenuBar.java | 21 +-- .../share/classes/java/awt/MenuComponent.java | 35 +++-- .../share/classes/java/awt/MenuItem.java | 34 +++-- .../share/classes/java/awt/PopupMenu.java | 7 +- .../WrongParentAfterRemoveMenu.java | 126 ++++++++++++++++++ 7 files changed, 218 insertions(+), 56 deletions(-) create mode 100644 jdk/test/java/awt/Menu/WrongParentAfterRemoveMenu/WrongParentAfterRemoveMenu.java diff --git a/jdk/src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java b/jdk/src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java index 470ad9a17d0..f966a767459 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java +++ b/jdk/src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java @@ -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,17 +22,24 @@ * 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.util.EventListener; -import java.io.ObjectOutputStream; -import java.io.ObjectInputStream; import java.io.IOException; -import javax.accessibility.*; -import sun.awt.AWTAccessor; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.EventListener; +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. @@ -43,7 +50,8 @@ import sun.awt.AWTAccessor; * of {@code CheckBoxMenuItem}: *

* Menu labeled Examples, containing items Basic, Simple, Check, and More Examples. The Check item is a CheckBoxMenuItem instance, in the off state. *

* The item labeled {@code Check} shows a check box menu item @@ -84,9 +92,9 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access * @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; diff --git a/jdk/src/java.desktop/share/classes/java/awt/Menu.java b/jdk/src/java.desktop/share/classes/java/awt/Menu.java index 70b5ee1f25f..4bd1bba8a0e 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Menu.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Menu.java @@ -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.Vector; import java.util.Enumeration; -import java.awt.peer.MenuPeer; -import java.awt.event.KeyEvent; -import javax.accessibility.*; +import java.util.Vector; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; + import sun.awt.AWTAccessor; /** @@ -78,7 +83,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { * @serial * @see #countItems() */ - Vector items = new Vector<>(); + private final Vector items = new Vector<>(); /** * This field indicates whether the menu has the @@ -92,7 +97,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { * @serial * @see #isTearOff() */ - boolean tearOff; + private final boolean tearOff; /** * This field will be set to {@code true} @@ -102,7 +107,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { * * @serial */ - boolean isHelpMenu; + volatile boolean isHelpMenu; private static final String base = "menu"; private static int nameCounter = 0; @@ -415,8 +420,8 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { if (peer != null) { peer.delItem(index); mi.removeNotify(); - mi.parent = null; } + mi.parent = null; } } diff --git a/jdk/src/java.desktop/share/classes/java/awt/MenuBar.java b/jdk/src/java.desktop/share/classes/java/awt/MenuBar.java index 4a57b0dbf2c..8d0d51d6360 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/MenuBar.java +++ b/jdk/src/java.desktop/share/classes/java/awt/MenuBar.java @@ -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.Vector; import java.util.Enumeration; +import java.util.Vector; + +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 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible * @serial * @see #countMenus() */ - Vector

menus = new Vector<>(); + private final Vector menus = new Vector<>(); /** * This menu is a special menu dedicated to @@ -106,7 +111,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible * @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 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible if (peer != null) { peer.delMenu(index); m.removeNotify(); - m.parent = null; } + m.parent = null; if (helpMenu == m) { helpMenu = null; m.isHelpMenu = false; diff --git a/jdk/src/java.desktop/share/classes/java/awt/MenuComponent.java b/jdk/src/java.desktop/share/classes/java/awt/MenuComponent.java index c6097397c98..fb3c72c617e 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/MenuComponent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/MenuComponent.java @@ -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.peer.MenuComponentPeer; import java.awt.event.ActionEvent; +import java.awt.peer.MenuComponentPeer; 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 @@ public abstract class MenuComponent implements java.io.Serializable { } 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 @@ public abstract class MenuComponent implements java.io.Serializable { * @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 @@ public abstract class MenuComponent implements java.io.Serializable { * @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 @@ public abstract class MenuComponent implements java.io.Serializable { * @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. diff --git a/jdk/src/java.desktop/share/classes/java/awt/MenuItem.java b/jdk/src/java.desktop/share/classes/java/awt/MenuItem.java index 3a70fe2bee0..e0611ccba31 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/MenuItem.java +++ b/jdk/src/java.desktop/share/classes/java/awt/MenuItem.java @@ -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.util.EventListener; -import java.io.ObjectOutputStream; -import java.io.ObjectInputStream; import java.io.IOException; -import javax.accessibility.*; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.EventListener; + +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 @@ public class MenuItem extends MenuComponent implements Accessible { * @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 @@ public class MenuItem extends MenuComponent implements Accessible { * @see #getLabel() * @see #setLabel(String) */ - String label; + volatile String label; /** * This field indicates the command that has been issued @@ -134,7 +144,7 @@ public class MenuItem extends MenuComponent implements Accessible { * @see #setActionCommand(String) * @see #getActionCommand() */ - String actionCommand; + private volatile String actionCommand; /** * The eventMask is ONLY set by subclasses via enableEvents. @@ -144,9 +154,9 @@ public class MenuItem extends MenuComponent implements Accessible { * * @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 @@ public class MenuItem extends MenuComponent implements Accessible { * @see #setShortcut(MenuShortcut) * @see #deleteShortcut() */ - private MenuShortcut shortcut = null; + private volatile MenuShortcut shortcut; private static final String base = "menuitem"; private static int nameCounter = 0; diff --git a/jdk/src/java.desktop/share/classes/java/awt/PopupMenu.java b/jdk/src/java.desktop/share/classes/java/awt/PopupMenu.java index 253351f164a..48460749d6e 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/PopupMenu.java +++ b/jdk/src/java.desktop/share/classes/java/awt/PopupMenu.java @@ -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 @@ public class PopupMenu extends Menu { private static final String base = "popup"; static int nameCounter = 0; - transient boolean isTrayIconPopup = false; + transient volatile boolean isTrayIconPopup; static { AWTAccessor.setPopupMenuAccessor( diff --git a/jdk/test/java/awt/Menu/WrongParentAfterRemoveMenu/WrongParentAfterRemoveMenu.java b/jdk/test/java/awt/Menu/WrongParentAfterRemoveMenu/WrongParentAfterRemoveMenu.java new file mode 100644 index 00000000000..18dc47912aa --- /dev/null +++ b/jdk/test/java/awt/Menu/WrongParentAfterRemoveMenu/WrongParentAfterRemoveMenu.java @@ -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"); + } + } +}