27 @summary Reference to the popup leaks after the TrayIcon is removed
28 @author Petr Pchelko
29 @library ../../../../lib/testlibrary/
30 @build ExtendedRobot
31 @run main/othervm -Xmx50m PopupMenuLeakTest
32 */
33
34 import java.awt.*;
35 import javax.swing.SwingUtilities;
36
37 import java.awt.image.BufferedImage;
38 import java.lang.ref.WeakReference;
39 import java.util.ArrayList;
40 import java.util.concurrent.atomic.AtomicReference;
41
42 public class PopupMenuLeakTest {
43
44 static final AtomicReference<WeakReference<TrayIcon>> iconWeakReference = new AtomicReference<>();
45 static final AtomicReference<WeakReference<PopupMenu>> popupWeakReference = new AtomicReference<>();
46 static ExtendedRobot robot;
47
48 public static void main(String[] args) throws Exception {
49 robot = new ExtendedRobot();
50 SwingUtilities.invokeAndWait(PopupMenuLeakTest::createSystemTrayIcon);
51 sleep();
52 // To make the test automatic we explicitly call addNotify on a popup to create the peer
53 SwingUtilities.invokeAndWait(PopupMenuLeakTest::addNotifyPopup);
54 sleep();
55 SwingUtilities.invokeAndWait(PopupMenuLeakTest::removeIcon);
56 sleep();
57 assertCollected(popupWeakReference.get(), "Failed, reference to popup not collected");
58 assertCollected(iconWeakReference.get(), "Failed, reference to tray icon not collected");
59 }
60
61 private static void addNotifyPopup() {
62 PopupMenu menu = popupWeakReference.get().get();
63 if (menu == null) {
64 throw new RuntimeException("Failed: popup collected too early");
65 }
66 menu.addNotify();
67 }
68
69 private static void removeIcon() {
70 TrayIcon icon = iconWeakReference.get().get();
71 if (icon == null) {
72 throw new RuntimeException("Failed: TrayIcon collected too early");
73 }
74 SystemTray.getSystemTray().remove(icon);
75 }
76
77 private static void assertCollected(WeakReference<?> reference, String message) {
78 java.util.List<byte[]> bytes = new ArrayList<>();
79 for (int i = 0; i < 5; i ++) {
80 try {
81 while (true) {
82 bytes.add(new byte[1024]);
83 }
84 } catch (OutOfMemoryError err) {
85 bytes = new ArrayList<>();
86 }
87 }
88 if (reference.get() != null) {
89 throw new RuntimeException(message);
90 }
91 }
92
93 private static void createSystemTrayIcon() {
94 final TrayIcon trayIcon = new TrayIcon(createTrayIconImage());
95 trayIcon.setImageAutoSize(true);
96
97 try {
98 // Add tray icon to system tray *before* adding popup menu to demonstrate buggy behaviour
99 trayIcon.setPopupMenu(createTrayIconPopupMenu());
100 SystemTray.getSystemTray().add(trayIcon);
101 iconWeakReference.set(new WeakReference<>(trayIcon));
102 popupWeakReference.set(new WeakReference<>(trayIcon.getPopupMenu()));
103 } catch (final AWTException awte) {
104 awte.printStackTrace();
105 }
120
121 trayImageGraphics.setColor(Color.red);
122
123 int trayIconImageInset = 4;
124 trayImageGraphics.fillOval(trayIconImageInset,
125 trayIconImageInset,
126 trayImage.getWidth() - 2 * trayIconImageInset,
127 trayImage.getHeight() - 2 * trayIconImageInset);
128
129 trayImageGraphics.setColor(Color.darkGray);
130
131 trayImageGraphics.drawOval(trayIconImageInset,
132 trayIconImageInset,
133 trayImage.getWidth() - 2 * trayIconImageInset,
134 trayImage.getHeight() - 2 * trayIconImageInset);
135
136 return trayImage;
137 }
138
139 private static PopupMenu createTrayIconPopupMenu() {
140 final PopupMenu trayIconPopupMenu = new PopupMenu();
141 final MenuItem popupMenuItem = new MenuItem("TEST!");
142 trayIconPopupMenu.add(popupMenuItem);
143 return trayIconPopupMenu;
144 }
145
146 private static void sleep() {
147 robot.waitForIdle(100);
148 }
149 }
|
27 @summary Reference to the popup leaks after the TrayIcon is removed
28 @author Petr Pchelko
29 @library ../../../../lib/testlibrary/
30 @build ExtendedRobot
31 @run main/othervm -Xmx50m PopupMenuLeakTest
32 */
33
34 import java.awt.*;
35 import javax.swing.SwingUtilities;
36
37 import java.awt.image.BufferedImage;
38 import java.lang.ref.WeakReference;
39 import java.util.ArrayList;
40 import java.util.concurrent.atomic.AtomicReference;
41
42 public class PopupMenuLeakTest {
43
44 static final AtomicReference<WeakReference<TrayIcon>> iconWeakReference = new AtomicReference<>();
45 static final AtomicReference<WeakReference<PopupMenu>> popupWeakReference = new AtomicReference<>();
46 static ExtendedRobot robot;
47 static Frame popupMenuParentFrame;
48
49 public static void main(String[] args) throws Exception {
50 robot = new ExtendedRobot();
51 SwingUtilities.invokeAndWait(PopupMenuLeakTest::createSystemTrayIcon);
52 sleep();
53 // To make the test automatic we explicitly call addNotify on a popup to create the peer
54 SwingUtilities.invokeAndWait(PopupMenuLeakTest::addNotifyPopup);
55 sleep();
56 SwingUtilities.invokeAndWait(PopupMenuLeakTest::removeIcon);
57 sleep();
58 assertCollected(popupWeakReference.get(), "Failed, reference to popup not collected");
59 assertCollected(iconWeakReference.get(), "Failed, reference to tray icon not collected");
60 }
61
62 private static void addNotifyPopup() {
63 PopupMenu menu = popupWeakReference.get().get();
64 if (menu == null) {
65 throw new RuntimeException("Failed: popup collected too early");
66 }
67 menu.addNotify();
68 }
69
70 private static void removeIcon() {
71 TrayIcon icon = iconWeakReference.get().get();
72 if (icon == null) {
73 throw new RuntimeException("Failed: TrayIcon collected too early");
74 }
75 SystemTray.getSystemTray().remove(icon);
76
77 PopupMenu menu = popupWeakReference.get().get();
78 popupMenuParentFrame.remove(menu);
79 popupMenuParentFrame.dispose();
80 }
81
82 private static void assertCollected(WeakReference<?> reference, String message) {
83 java.util.List<byte[]> bytes = new ArrayList<>();
84 for (int i = 0; i < 5; i ++) {
85 try {
86 while (true) {
87 bytes.add(new byte[1024]);
88 }
89 } catch (OutOfMemoryError err) {
90 }
91 }
92 if (reference.get() != null) {
93 throw new RuntimeException(message);
94 }
95 }
96
97 private static void createSystemTrayIcon() {
98 final TrayIcon trayIcon = new TrayIcon(createTrayIconImage());
99 trayIcon.setImageAutoSize(true);
100
101 try {
102 // Add tray icon to system tray *before* adding popup menu to demonstrate buggy behaviour
103 trayIcon.setPopupMenu(createTrayIconPopupMenu());
104 SystemTray.getSystemTray().add(trayIcon);
105 iconWeakReference.set(new WeakReference<>(trayIcon));
106 popupWeakReference.set(new WeakReference<>(trayIcon.getPopupMenu()));
107 } catch (final AWTException awte) {
108 awte.printStackTrace();
109 }
124
125 trayImageGraphics.setColor(Color.red);
126
127 int trayIconImageInset = 4;
128 trayImageGraphics.fillOval(trayIconImageInset,
129 trayIconImageInset,
130 trayImage.getWidth() - 2 * trayIconImageInset,
131 trayImage.getHeight() - 2 * trayIconImageInset);
132
133 trayImageGraphics.setColor(Color.darkGray);
134
135 trayImageGraphics.drawOval(trayIconImageInset,
136 trayIconImageInset,
137 trayImage.getWidth() - 2 * trayIconImageInset,
138 trayImage.getHeight() - 2 * trayIconImageInset);
139
140 return trayImage;
141 }
142
143 private static PopupMenu createTrayIconPopupMenu() {
144 popupMenuParentFrame = new Frame();
145 popupMenuParentFrame.setSize(200, 200);
146 popupMenuParentFrame.setVisible(true);
147
148 final PopupMenu trayIconPopupMenu = new PopupMenu();
149 final MenuItem popupMenuItem = new MenuItem("TEST!");
150 trayIconPopupMenu.add(popupMenuItem);
151
152 popupMenuParentFrame.add(trayIconPopupMenu);
153 return trayIconPopupMenu;
154 }
155
156 private static void sleep() {
157 robot.waitForIdle(100);
158 }
159 }
|