JDK-6358034 : NPE in Win32GraphicsEnvironment.displayChanged when switching display mode
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 5.0,6
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic,windows_xp
  • CPU: generic,x86
  • Submitted: 2005-12-01
  • Updated: 2010-04-02
  • Resolved: 2006-02-22
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
6 b73Fixed
Related Reports
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_01-b08)
Java HotSpot(TM) Client VM (build 1.5.0_01-b08, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [version 5.1.2600]

Service Pack 2

EXTRA RELEVANT SYSTEM CONFIGURATION :
ATI Mobility radeon 9700 graphics card

A DESCRIPTION OF THE PROBLEM :
When AWT is active, switching display mode from the Windows control panel results in the following exception from the AWT thread:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at sun.awt.Win32GraphicsEnvironment.displayChanged(Unknown Source)
        at sun.awt.windows.WToolkit$4.run(Unknown Source)
        at java.awt.event.InvocationEvent.dispatch(Unknown Source)
        at java.awt.EventQueue.dispatchEvent(Unknown Source)
        at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)

        at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.run(Unknown Source)

This is especially annoying for us, since we're developing games using LWJGL (http://lwjgl.org) which switches display mode without using AWT. The exception occurs in that case too. Although the game seems to runs fine even after the exception, one never knows what internal invariant might be broken.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Compile and run the attached program
2. Go to the display properties control panel and select a different display mode.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No exception is thrown.
ACTUAL -
An exception is thrown:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at sun.awt.Win32GraphicsEnvironment.displayChanged(Unknown Source)
        at sun.awt.windows.WToolkit$4.run(Unknown Source)
        at java.awt.event.InvocationEvent.dispatch(Unknown Source)
        at java.awt.EventQueue.dispatchEvent(Unknown Source)
        at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)

        at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.run(Unknown Source)

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at sun.awt.Win32GraphicsEnvironment.displayChanged(Unknown Source)
        at sun.awt.windows.WToolkit$4.run(Unknown Source)
        at java.awt.event.InvocationEvent.dispatch(Unknown Source)
        at java.awt.EventQueue.dispatchEvent(Unknown Source)
        at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)

        at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.run(Unknown Source)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.*;

public class test {
	public static void main(String[] args) throws Exception {
		Toolkit.getDefaultToolkit();
System.out.println("AWT initialized, please switch mode now");
		Thread.sleep(10000000);
	}
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Don't switch mode while java programs are running :)
Contribution by java.net member dmytro_sheyko:

A DESCRIPTION OF THE FIX :
  Bug number : 6358034
  Bug Description : NPE in Win32GraphicsEnvironment.displayChanged when switching display mode
Diff Baseline : Mustang b67.
Diff :
--- src\windows\classes\sun\awt\Win32GraphicsEnvironment.java	Tue Jan 17 10:49:04 2006
+++ src\windows\classes\sun\awt\Win32GraphicsEnvironment.java	Fri Jan 20 13:08:42 2006
@@ -125,9 +125,10 @@
 
     /*
      * Updates the array of screen devices to the current configuration.
-     * Returns the previous array of screen devices.
+     * Returns the previous array of screen devices,
+     * which may be empty but never null.
      */
-    public synchronized GraphicsDevice[] resetDisplays() {
+    private synchronized GraphicsDevice[] resetDisplays() {
         // REMIND : We should go through the array and update any displays
         // which may have been added or removed.  Also, we should update
         // any display state information which may now be different.
@@ -137,8 +138,10 @@
         // changes, and because programs may keep references to those
         // java objects.
         GraphicsDevice[] ret = screens;
-        return ret;
+        return (ret == null)? EMPTY_ARRAY_OF_GraphicsDevice: ret;
     }
+        // where
+        private static final GraphicsDevice[] EMPTY_ARRAY_OF_GraphicsDevice = new GraphicsDevice[0];
 
 /*
  * ----END DISPLAY CHANGE SUPPORT----


JUnit TESTCASE :
import java.awt.GraphicsEnvironment;

import junit.framework.TestCase;

public class Bug6358034Test extends TestCase {

	public void test() throws Exception {
		GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
		// NullPointerException does not have to be thrown
		((sun.awt.Win32GraphicsEnvironment) ge).displayChanged();
	}

	public static void main(String[] args) {
		junit.textui.TestRunner.run(Bug6358034Test.class);
	}

}


FIX FOR BUG NUMBER:
6358034

Comments
EVALUATION The contributor came up with a better version of the fix which was eventually integrated, see the thread on the collaboration site for details.
04-02-2006

EVALUATION It also occured to me that I don't see any reasons we should keep resetDisplays() method around. We should just fold it into Win32GE.displayChanged() (along with the comments) and add a null check before iterating through the array entries.
25-01-2006

EVALUATION The suggested fix looks reasonable. One tweak: since the displayChange events are relatively rare (and the case where the device array is empty is even more rare) and the result of the resetDisplays() method is a throwaway, I think we can create an empty array on the fly.
25-01-2006

EVALUATION Contribution-forum:https://jdk-collaboration.dev.java.net/servlets/ProjectForumMessageView?forumID=1463&messageID=10978
23-01-2006

EVALUATION We get an NPE at line 107 when trying to access the list of GraphicsDevices. The list is normally generated when SunGraphicsEnvironment.getScreenDevices() is called. But in this scenario no gui is initialized and getScreenDevices is not called, so the 'screens' is not set, and we get an NPE.
02-12-2005