JDK-4455041 : AWT code causes images in a Powerpoint doc to disappear
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.3.0,1.4.1
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2001-05-06
  • Updated: 2002-07-09
  • Resolved: 2002-04-04
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.
Other Other
1.3.1_05 05Fixed 1.4.1Fixed
Related Reports
Duplicate :  
Description

Name: boT120536			Date: 05/06/2001


java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)

1. compile the following code:

import java.awt.*;

public class testawt3 extends java.awt.Frame {

    Image backImg;
    
    public testawt3() {
    }
    
    public void paint(Graphics g) {
	try {
	    Dimension dim = getSize();
	    
	    if (backImg == null) {
		backImg = createImage(dim.width, dim.height);
	    } else if ((backImg.getWidth(null) != dim.width) ||
		       (backImg.getHeight(null) != dim.height))
		{
		    backImg.flush();
		    backImg = createImage(dim.width, dim.height);
		}
     
	    if (backImg != null) {
	     	Graphics bg = backImg.getGraphics();
	     	try {
		    System.out.println("no super paint\n");
		    // super.paint(bg);

		    System.out.println("yes draw image\n");
	     	    g.drawImage(backImg, 0, 0, null);  // this is the line that
		    // is causing the problem
		    
		} finally {
		    bg.dispose();
		}
	    }
	         
	    return;
	} catch (Exception e) {
              // running on Solaris
              // sometimes Windows AWT throws NPE on drawImage()
          }
    }
    
    public static void main(String args[]) {
	System.out.println("testawt3\n");

	testawt3 test = new testawt3();
	test.show();
    }
}
 

2. Put these script in a batch file call testawt3.bat

REM -- This is for debugging only --
@set JDK12HOME=c:\\jdk1.3.1
%JDK12HOME%\jre\bin\java testawt3 %1% %2% %3% %4% %5% %6% %7% %8% %9%

3. Run this file as a Windows Service, to set it up follow the step

4. Get instsrv.exe and srvany.exe (part of the NT-resource kit)
5. Put srvany.exe in the txguardian directory
6. Run instsrv.exe like this:

instsrv testawt3 <testawt3-directory>\srvany.exe

4. Edit the registry, add a subkey called Parameters in

HKEY_Local_Machine\SYSTEM\CurrentControlSet\Services\testawt3

then create these string-values in that subkey

Application = c:\winnt\system32\cmd /k
AppParameters = <testawt3-directory>\testawt3.bat
AppDirectory = <testawt3-directory>

5. Start the testawt3 service, a console window should pop up
   then you will see the awt.frame pops up,

6. Resize the frame (that will causes the paint rountine in the testawt3 class
   to execute)

7. Open the Powerpoint document (you will see that some images on the top-right
   are missing)

8. Stop the testawt3 service, close the console window and the testawt3 frame

9. Open the Powerpoint document (you will see that those images that were
missing appears)

If I comment out the "drawImage" call in paint, then
the problem will go out, so I suspect that it is with the dramImage
method. This problem can be easily and consistenly reproduced.
Although sometimes, it will seems to work fine, but if
you reboot the machine then the problem can be reproduce
again consistenly.
(Review ID: 123743) 
======================================================================

Important note:
When installing the service as described above, it is important to change
the properties of the service as follows: In the "LogOn" tab of the properties
dialog for the service, check the "Allow service to interact with desktop".
This allows the program to actually run; without that option checked, the app
does not run and the problem is not apparent.

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: 1.3.1_05 hopper FIXED IN: 1.3.1_05 hopper INTEGRATED IN: 1.3.1_05 hopper
14-06-2004

WORK AROUND Name: boT120536 Date: 05/06/2001 Doens't seem to have one. ======================================================================
11-06-2004

SUGGESTED FIX ------- Win32GraphicsDevice.java ------- *** /tmp/dfaayGa Wed Mar 13 13:25:59 2002 --- Win32GraphicsDevice.java Wed Mar 6 14:27:23 2002 *************** *** 52,57 **** --- 52,58 ---- private static boolean ddDisabled; private static boolean ddUsed; private static boolean ddInitialized; + private static boolean pfDisabled; private static AWTPermission fullScreenExclusivePermission; static { *************** *** 59,64 **** --- 60,74 ---- new sun.security.action.GetPropertyAction("sun.java2d.noddraw")); ddDisabled = (noddraw != null && noddraw.length() > 0 && noddraw.charAt(0) == 't'); + + // 4455041 - Even when ddraw is disabled, ddraw.dll is loaded when + // pixel format calls are made. This causes problems when a Java app + // is run as an NT service. To prevent the loading of ddraw.dll + // completely, sun.awt.nopixfmt should be set as well. Apps which use + // OpenGL w/ Java probably don't want to set this. + String nopixfmt = (String)java.security.AccessController.doPrivileged( + new sun.security.action.GetPropertyAction("sun.awt.nopixfmt")); + pfDisabled = (nopixfmt != null); initIDs(); } *************** *** 129,135 **** defaultPixID = getDefaultPixID(screen); Vector v = new Vector( max ); if (defaultPixID == 0) { ! //Workaround for failing GDI calls defaultConfig = Win32GraphicsConfig.getConfig(this, defaultPixID); v.addElement(defaultConfig); --- 139,145 ---- defaultPixID = getDefaultPixID(screen); Vector v = new Vector( max ); if (defaultPixID == 0) { ! //Workaround for failing GDI calls, or if DirectDraw is disabled defaultConfig = Win32GraphicsConfig.getConfig(this, defaultPixID); v.addElement(defaultConfig); *************** *** 156,166 **** } /** ! * Returns the maximum number of graphics configurations available. * This number is less than or equal to the number of graphics * configurations supported. */ ! protected native int getMaxConfigs(int screen); /** * Returns whether or not the PixelFormat indicated by index is --- 166,185 ---- } /** ! * Returns the maximum number of graphics configurations available, or 1 ! * if PixelFormat calls fail or are disabled. * This number is less than or equal to the number of graphics * configurations supported. */ ! protected int getMaxConfigs(int screen) { ! if (pfDisabled) { ! return 1; ! } else { ! return getMaxConfigsImpl(screen); ! } ! } ! ! private native int getMaxConfigsImpl(int screen); /** * Returns whether or not the PixelFormat indicated by index is *************** *** 168,173 **** --- 187,194 ---- * (PFD_DRAW_TO_WINDOW), support GDI (PFD_SUPPORT_GDI), and in the * case of an 8-bit format (cColorBits <= 8) uses indexed colors * (iPixelType == PFD_TYPE_COLORINDEX). + * We use the index 0 to indicate that PixelFormat calls don't work, or + * are disabled. Do not call this function with an index of 0. * @param index a PixelFormat index */ protected native boolean isPixFmtSupported(int index, int screen); *************** *** 174,182 **** /** * Returns the PixelFormatID of the default graphics configuration ! * associated with this graphics device. */ ! protected native int getDefaultPixID(int screen); /** * Returns the default graphics configuration --- 195,216 ---- /** * Returns the PixelFormatID of the default graphics configuration ! * associated with this graphics device, or 0 if PixelFormats calls fail or ! * are disabled. */ ! protected int getDefaultPixID(int screen) { ! if (pfDisabled) { ! return 0; ! } else { ! return getDefaultPixIDImpl(screen); ! } ! } ! ! /** ! * Returns the default PixelFormat ID from GDI. Do not call if PixelFormats ! * are disabled. ! */ ! private native int getDefaultPixIDImpl(int screen); /** * Returns the default graphics configuration ------- awt_Win32GraphicsDevice.cpp ------- *** /tmp/dCcaiHa Wed Mar 13 13:25:59 2002 --- awt_Win32GraphicsDevice.cpp Tue Mar 12 17:16:15 2002 *************** *** 734,744 **** /* * Class: sun_awt_Win32GraphicsDevice ! * Method: getMaxConfigs * Signature: ()I */ ! JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getMaxConfigs (JNIEnv* jniEnv, jobject theThis, jint screen) { TRY; HDC hDC = getDCFromScreen(screen); --- 734,744 ---- /* * Class: sun_awt_Win32GraphicsDevice ! * Method: getMaxConfigsImpl * Signature: ()I */ ! JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getMaxConfigsImpl (JNIEnv* jniEnv, jobject theThis, jint screen) { TRY; HDC hDC = getDCFromScreen(screen); *************** *** 770,775 **** --- 770,779 ---- TRY; jboolean suppColor = JNI_TRUE; HDC hDC = getDCFromScreen(screen); + + if (pixFmtID == 0) { + return true; + } PIXELFORMATDESCRIPTOR pfd; int max = ::DescribePixelFormat(hDC, (int)pixFmtID, *************** *** 799,809 **** /* * Class: sun_awt_Win32GraphicsDevice ! * Method: getDefaultPixID ! * Signature: ()I */ ! JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getDefaultPixID (JNIEnv* env, jobject theThis, jint screen) { TRY; int pixFmtID = 0; --- 803,813 ---- /* * Class: sun_awt_Win32GraphicsDevice ! * Method: getDefaultPixIDImpl ! * Signature: (I)I */ ! JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getDefaultPixIDImpl (JNIEnv* env, jobject theThis, jint screen) { TRY; int pixFmtID = 0;
11-06-2004

EVALUATION Problems with rendering images are usually handled by 2D. eric.hawkes@eng 2001-05-06 It looks like there is a fundamental problem in win2k with loading ddraw inside a Windows NT service. I can take this problem completely outside Java and demonstrate the problem as follows: - Here's a sample app that you can run as a service instead of the supplied Java app. Follow the directions for the Java app, but use this as an executable instead: #include <windows.h> #include <stdio.h> void main(int argc, char **argv) { ::LoadLibrary("ddraw.dll"); while (1) { printf("Sleeping\n"); Sleep(1000); } } (compile the app using msdev's cl compiler). - When starting the service, you should see a command console pop up and start printing "Sleeping" every second. - Now try to run any Java app at all. Or, to make the problem even clearer, run a non-Java app that uses ddraw. This includes the powerpoint app described. - See the resulting problems. In the powerpoint doc, you should see missing images, as described. If you run a ddraw app (such as one of the sample apps from the sdk) you should see that it cannot run at all. - Stop the service and make sure that the service app is not running (you may need to kill that app in the Task Manager). - Run the ddraw app again and see that it functions normally. This is obviously not a problem in Java, but is a fundamental flaw in the way that WindowsNT interacts with ddraw. Presumably there is a problem running (or even loading) ddraw into the kernel and this is the root of the issue. In any case, we can hardly fix this problem in Java. We should be able to work around the problem. The obvious workaround has been tried: run java with -Dsun.java2d.noddraw=true. This usually solves ddraw-related problems. However, it did not fix the problem in this case because the problem comes not from what we are doing with ddraw but from the act of simply loading the library. the flag actually prevents us from loading the library directly, but we issue a couple of calls related to pixel formats which (on NT systems) load opengl32.dll; this, in turn, loads ddraw.dll. I believe the fix should be to prevent any opengl-related calls from being issued if the noddraw flag has been set. This will result in invalid pixel format information, but we should be able to deal with that with some default values. But I need to validate this workaround/fix with the AWT team. chet.haase@Eng 2001-08-09 Additional info: I reproduced the bug as described above on an ATI Rage Pro Turbo video card, driver version 5.0.2195.4018. When I tried the same test on my Matrox G400 DualHead card instead, I could not reproduce the problem. Could be a video card win2k driver problem instead of a Microsoft bug. chet.haase@Eng 2001-08-09 More info: Microsoft admits this is a problem with DirectX (although they thought it was not video-card specific), supposedly fixed in DX8.1. We still need to workaround the problem in our code, however, since we cannot affect the version of DirectX installed on the user's system. ###@###.### 2001-09-13 There may be problems with Java3D if we sidestep PixelFormat calls when DirectDraw is disabled. ###@###.### 2001-09-20 I added a new flag, sun.awt.nopixfmt, which if set, prevent PixelFormat calls from being made. I finally tracked down a machine which exhibited the bug, and this fixed the problem. ###@###.### 2002-03-13
13-03-2002