United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6547881 NPE when closing modal dialog
JDK-6547881 : NPE when closing modal dialog

Details
Type:
Bug
Submit Date:
2007-04-19
Status:
Closed
Updated Date:
2011-03-07
Project Name:
JDK
Resolved Date:
2011-03-07
Component:
client-libs
OS:
linux
Sub-Component:
java.awt
CPU:
x86
Priority:
P2
Resolution:
Fixed
Affected Versions:
7
Fixed Versions:

Related Reports
Backport:
Backport:
Backport:
Relates:

Sub Tasks

Description
Run the test, you will see two frames and one modal dialog, close the dialog, NPE occured.
Also you may noticed that second frame may be moved above modal dialog.

import java.awt.Dialog;
import java.awt.Frame;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class npe_test {
    public static void main(String[] args)
    {
        Frame frame1 = new Frame("frame 1");
        frame1.setBounds(0, 0, 100, 100);
        frame1.setVisible(true);
        try {
            Thread.sleep(500);
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        }
        Frame frame2 = new Frame("frame 2");
        frame2.setBounds(150, 0, 100, 100);
        frame2.setVisible(true);
        try {
            Thread.sleep(500);
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        }

        Frame frame3 = new Frame("frame 3");
        Dialog dialog = new Dialog(frame3, "dialog", true);
        dialog.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent we) {
                    we.getWindow().dispose();
                }
            });
        dialog.setBounds(300, 0, 100, 100);
        dialog.setVisible(true);
        frame1.dispose();
        frame2.dispose();
        frame3.dispose();
    }
}

                                    

Comments
EVALUATION

this is a regression cused by fix for  6518077 (Modal dialogs open slowly with JRE 1.6.0 sun.awt.X11.XToolkit)

mappedWindowsCount field was added to avoid unnecessary XQueryTree() in collerctJavaToplevels().
But actually XQueryTree() returns all childs, not only mapped.
And when we show a modal dialog we call XDialogPeer.blockWindows() to block all toplevel it should block.  In this methods we try to collect all java toplevels we have 
(XWindowPeer.collectJavaToplevels()), since the dialog itself is not mapped yet 
mappedWindowCount is less then actual number of toplevels we can find useing XQueryTree(),
so we collect no all toplevels and missed one will not be blocked at all.
And when we will try to unblock it we got NPE :(

So, to fix the problem we should not use nu,ber of mapped toplevels, but just number of 
toplevels (there is windows Set in XWindowPeer which could be used for this).
                                     
2007-04-19
SUGGESTED FIX

+++ XWindowPeer.java        2007-04-19 19:22:27.000000000 +0400
@@ -56,12 +56,12 @@
     private static final Logger focusLog = Logger.getLogger("sun.awt.X11.focus.XWindowPeer");
     private static final Logger insLog = Logger.getLogger("sun.awt.X11.insets.XWindowPeer");
     private static final Logger grabLog = Logger.getLogger("sun.awt.X11.grab.XWindowPeer");
     private static final Logger iconLog = Logger.getLogger("sun.awt.X11.icon.XWindowPeer");
 
-    private static Set windows = new HashSet();
-    private static int mappedWindowsCount = 0;
+    // should be synchronized on awtLock
+    private static Set<XWindowPeer> windows = new HashSet<XWindowPeer>();
 
     static XAtom wm_protocols;
     static XAtom wm_delete_window; 
     static XAtom wm_take_focus;
 
@@ -139,27 +139,26 @@
         params.putIfNull(BIT_GRAVITY, Integer.valueOf(NorthWestGravity));
 
         savedState = WithdrawnState;
         XA_NET_WM_STATE = XAtom.get("_NET_WM_STATE");
 
-        windows.add(this);
-
         winAttr = new XWindowAttributesData();
         insets = new Insets(0,0,0,0);
 
         params.put(OVERRIDE_REDIRECT, Boolean.valueOf(isOverrideRedirect()));
 
-        XToolkit.awtLock();
+        SunToolkit.awtLock();
         try {
+            windows.add(this);
             if (wm_protocols == null) {
                 wm_protocols = XAtom.get("WM_PROTOCOLS");
                 wm_delete_window = XAtom.get("WM_DELETE_WINDOW");
                 wm_take_focus = XAtom.get("WM_TAKE_FOCUS");
             }
         }
         finally {
-            XToolkit.awtUnlock();
+            SunToolkit.awtUnlock();
         }
         cachedFocusableWindow = isFocusableWindow();
 
         Font f = target.getFont();
         if (f == null) {
@@ -857,16 +856,13 @@
         //
         // make new hash of toplevels of all windows from 'windows' hash.
         // FIXME: do not call them "toplevel" as it is misleading.
         //
         HashSet toplevels = new HashSet();
-        Iterator it = windows.iterator();
-        XWindowPeer xp = null;
         long topl = 0, mytopl = 0;
 
-        while( it.hasNext() ) {
-            xp = (XWindowPeer)(it.next());
+        for (XWindowPeer xp : windows) {
             topl = getToplevelWindow( xp.getWindow() );
             if( xp.equals( this ) ) {
                 mytopl = topl;
             }
             if( topl > 0 )
@@ -1074,11 +1070,16 @@
         return XWM.getWMID() == XWM.OPENLOOK_WM &&
             winAttr.nativeDecor == false;
     }
 
     public void dispose() {
-        windows.remove(this);
+        SunToolkit.awtLock();
+        try {
+            windows.remove(this);
+        } finally {
+            SunToolkit.awtUnlock();
+        }
         if (warningWindow != null) {
             warningWindow.destroy();
         }
         removeRootPropertyEventDispatcher();
         mustControlStackPosition = false;
@@ -1151,11 +1152,10 @@
         isBeforeFirstMapNotify = false;
         updateAlwaysOnTop();
 
         synchronized (getStateLock()) {
             if (!isMapped) {
-                mappedWindowsCount++;
                 isMapped = true;
             }
         }
     }
 
@@ -1166,11 +1166,10 @@
         // So we also check for the property later in MapNotify. See 6480534.
         isUnhiding |= isWMStateNetHidden();
 
         synchronized (getStateLock()) {
             if (isMapped) {
-                mappedWindowsCount--;
                 isMapped = false;
             }
         }
     }
 
@@ -1306,11 +1305,12 @@
                 v.add(rootWindow);
             }
         } else {
             v.add(XToolkit.getDefaultRootWindow());
         }
-        while ((v.size() > 0) && (javaToplevels.size() < mappedWindowsCount)) {
+        final int windowsCount = windows.size();
+        while ((v.size() > 0) && (javaToplevels.size() < windowsCount)) {
             long win = v.remove(0);
             XQueryTree qt = new XQueryTree(win);
             try {
                 if (qt.execute() != 0) {
                     int nchildren = qt.get_nchildren();
                                     
2007-04-19



Hardware and Software, Engineered to Work Together