JDK-6547881 : NPE when closing modal dialog
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 7
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2007-04-19
  • Updated: 2011-03-07
  • Resolved: 2011-03-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7
6u16-revFixed 7 b14Fixed
Related Reports
Relates :  
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
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();
19-04-2007

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).
19-04-2007