8039081: [TEST_BUG] Test java/awt/TrayIcon/PopupMenuLeakTest/PopupMenuLeakTest.java fails
authorarapte
Fri, 05 Aug 2016 15:48:37 +0530
changeset 40425 5f77c9f08911
parent 40424 c776f49ac7e1
child 40426 8b413b0e064c
8039081: [TEST_BUG] Test java/awt/TrayIcon/PopupMenuLeakTest/PopupMenuLeakTest.java fails Reviewed-by: serb, psadhukhan
jdk/src/java.desktop/share/classes/java/awt/TrayIcon.java
jdk/src/java.desktop/unix/classes/sun/awt/X11/XTrayIconPeer.java
jdk/test/java/awt/TrayIcon/PopupMenuLeakTest/PopupMenuLeakTest.java
--- a/jdk/src/java.desktop/share/classes/java/awt/TrayIcon.java	Wed Aug 03 15:18:58 2016 +0800
+++ b/jdk/src/java.desktop/share/classes/java/awt/TrayIcon.java	Fri Aug 05 15:48:37 2016 +0530
@@ -703,6 +703,9 @@
         synchronized (this) {
             p = peer;
             peer = null;
+            if (popup != null) {
+                popup.removeNotify();
+            }
         }
         if (p != null) {
             p.dispose();
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTrayIconPeer.java	Wed Aug 03 15:18:58 2016 +0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTrayIconPeer.java	Fri Aug 05 15:48:37 2016 +0530
@@ -93,7 +93,6 @@
 
         if (XWM.getWMID() != XWM.METACITY_WM) {
             parentXED = dummyXED; // We don't like to leave it 'null'.
-
         } else {
             parentXED = new XEventDispatcher() {
                 // It's executed under AWTLock.
@@ -300,10 +299,19 @@
 
         removeXED(getWindow(), eframeXED);
         removeXED(eframeParentID, parentXED);
+        removeListeners();
         eframe.realDispose();
         balloon.dispose();
+        tooltip.dispose();
         isTrayIconDisplayed = false;
+        canvas.dispose();
+        canvas = null;
+        popup = null;
+        balloon = null;
+        tooltip = null;
         XToolkit.targetDisposedPeer(target, this);
+        target = null;
+        eframe = null;
     }
 
     public static void suppressWarningString(Window w) {
@@ -416,6 +424,12 @@
         eframe.addMouseListener(eventProxy);
     }
 
+    void removeListeners() {
+        canvas.removeMouseListener(eventProxy);
+        canvas.removeMouseMotionListener(eventProxy);
+        eframe.removeMouseListener(eventProxy);
+    }
+
     long getWindow() {
         return AWTAccessor.getComponentAccessor()
                           .<XEmbeddedFramePeer>getPeer(eframe).getWindow();
@@ -550,6 +564,11 @@
 
             super.repaintImage(doClear || (old_autosize != autosize));
         }
+
+        public void dispose() {
+            super.dispose();
+            target = null;
+        }
     }
 
     @SuppressWarnings("serial") // JDK-implementation class
@@ -573,6 +592,10 @@
             repaintImage(true);
         }
 
+        public void dispose() {
+            observer = null;
+        }
+
         // Invoke on EDT.
         protected void repaintImage(boolean doClear) {
             Graphics g = getGraphics();
--- a/jdk/test/java/awt/TrayIcon/PopupMenuLeakTest/PopupMenuLeakTest.java	Wed Aug 03 15:18:58 2016 +0800
+++ b/jdk/test/java/awt/TrayIcon/PopupMenuLeakTest/PopupMenuLeakTest.java	Fri Aug 05 15:48:37 2016 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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,25 @@
  */
 
 /*
- @test
- @key headful
-  @bug 8007220
-  @summary Reference to the popup leaks after the TrayIcon is removed
-  @author Petr Pchelko
+  @test
+  @key headful
+  @bug 8007220 8039081
+  @summary Reference to the popup leaks after the TrayIcon is removed.
+  @requires os.family != "windows"
   @library ../../../../lib/testlibrary/
   @build ExtendedRobot
   @run main/othervm -Xmx50m PopupMenuLeakTest
  */
 
-import java.awt.*;
+import java.awt.AWTException;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.MenuItem;
+import java.awt.PopupMenu;
+import java.awt.RenderingHints;
+import java.awt.SystemTray;
+import java.awt.TrayIcon;
 import javax.swing.SwingUtilities;
 
 import java.awt.image.BufferedImage;
@@ -45,7 +53,6 @@
     static final AtomicReference<WeakReference<TrayIcon>> iconWeakReference = new AtomicReference<>();
     static final AtomicReference<WeakReference<PopupMenu>> popupWeakReference = new AtomicReference<>();
     static ExtendedRobot robot;
-
     public static void main(String[] args) throws Exception {
         robot = new ExtendedRobot();
         SwingUtilities.invokeAndWait(PopupMenuLeakTest::createSystemTrayIcon);
@@ -55,8 +62,8 @@
         sleep();
         SwingUtilities.invokeAndWait(PopupMenuLeakTest::removeIcon);
         sleep();
+        assertCollected(iconWeakReference.get(), "Failed, reference to tray icon not collected");
         assertCollected(popupWeakReference.get(), "Failed, reference to popup not collected");
-        assertCollected(iconWeakReference.get(), "Failed, reference to tray icon not collected");
     }
 
     private static void addNotifyPopup() {
@@ -78,12 +85,17 @@
     private static void assertCollected(WeakReference<?> reference, String message) {
         java.util.List<byte[]> bytes = new ArrayList<>();
         for (int i = 0; i < 5; i ++) {
+            if (reference.get() == null) {
+                // reference is collected, avoid OOMs.
+                break;
+            }
             try {
                 while (true) {
-                    bytes.add(new byte[1024]);
+                    bytes.add(new byte[4096]);
                 }
             } catch (OutOfMemoryError err) {
-                bytes = new ArrayList<>();
+                bytes.clear();
+                causeGC();
             }
         }
         if (reference.get() != null) {
@@ -91,6 +103,13 @@
         }
     }
 
+    private static void causeGC() {
+        System.gc();
+        System.runFinalization();
+        robot.delay(1000);
+    }
+
+
     private static void createSystemTrayIcon() {
         final TrayIcon trayIcon = new TrayIcon(createTrayIconImage());
         trayIcon.setImageAutoSize(true);