Java
Java SE
2.3.1 General Unresolved Keyboard Issues
2.3.2 Linux and Solaris 10 OS x86 Keyboard Issues
2.4.2 Using Modal Dialogs from Applets
2.5.1 Troubleshooting Memory Leaks
2.6.1 How to Distinguish an AWT Crash
2.6.2 How to Troubleshoot a Crash in AWT
2.7.1 How to Trace Focus Events
2.7.1.1 Communication With Native Focus System
2.7.2 Focus System in the Plugin
2.7.3 Focus Models Supported by X Window Managers
2.7.5 Miscellaneous Problems With Focus
2.8.1 Debugging Drag and Drop Applications
2.8.2 Frequent Issues With Drag and Drop
This chapter provides information and guidance on some specific procedures for troubleshooting some of the most common issues that might be found in the Java SE AWT API:
The following AWT debugging tips can be helpful:
Solaris OS and Linux only: To trace X11 errors, set NOISY_AWT=true.
To dump the AWT component hierarchy, press Ctrl+Shift+F1.
If the application hangs, get a stack trace with Ctrl+\ (SIGQUIT) on Solaris OS and Linux or Ctrl+Break on Windows.
This section describes some possible problems with layout and provides workarounds when available.
Cause: Due to some specifics of the layout manager GridBagLayout, if ipadx or ipady is set, and if invalidate() and validate() are called, then Component size increases to the value of ipadx or ipady. This happens because the layout manager GridBagLayout iteratively calculates the amount of space needed to store the component within the container.
Workaround: The JDK does not provide a reliable and simple way to detect if the layout manager should rearrange components or not in such a case, but there is a very simple workaround. Use components with the overridden method getPreferredSize(), which always returns the current needed size.
public Dimension getPreferredSize(){
return new Dimension(size+xpad*2+1, size+ypad*2+1);
}
Cause: Invoking validate() from any Container.doLayout() method can lead to infinite recursion because AWT itself invokes doLayout() from validate().
This section describes issues with key events.
The following keyboard issues are currently unresolved.
On some non-English keyboards certain accented keys are engraved on the keytop and therefore are primary layer characters. Nevertheless, they cannot be used for mnemonics because there is no corresponding Java keycode.
Changing the default locale at runtime does not change the text that is displayed for the menu accelerator keys.
On a standard 109-key Japanese keyboard, the yen key and the backslash key both generate a backslash, because they have the same charCode for the WM_CHAR message. AWT should distinguish them. This will be fixed in a future release.
The following keyboard issues concern the Linux and Solaris 10 OS x86 systems.
Keyboard input in these systems is usually based on XKEYBOARD X Window extension. Users can configure only one keyboard layout (for instance, Danish: dk) or several layouts to switch between (for example, us and dk).
With some keyboard layouts, for instance sk, hu, and cz, pressing the NumPad decimal separator not only enters a delimiter but also deletes the previous character. This is due to a native bug. A workaround is to use two layouts, for example, us and sk. In this case the numeric keypad works correctly in both layouts.
On UNIX systems that support dynamic keyboard changes, a running Java application does not recognize such a change. For instance, changing the keyboard from US to German does not change the keyboard mapping. Although the X server detects the change and sends out a MappingNotify event to interested clients, AWT does not refresh its notion of the keycode-keysym mapping.
With the Java SE 6 release, many problems were fixed and many improvements were implemented in the area of AWT modality. If you observe a modality problem with Java SE 1.5 or an earlier release, first upgrade to the Java SE 6 release to see if the problem has been already fixed. Some of the problems that were fixed in Java SE 6 are the following:
Modal dialog goes behind a blocked frame.
Two modal dialogs with the same parent window opened at the same time.
Many of the modality improvements are unavailable in some Solaris OS or Linux environments, for example, when using CDE window managers. With Java SE 6, to see if a modality type or modal exclusion type is supported in particular configuration, use the methods Toolkit.isModalityTypeSupported() and Toolkit.isModalExclusionTypeSupported().
Another problem exists when running Java modal dialogs on Solaris OS or Linux. When a modal dialog appears on the screen, the window manager might hide some of the Java top-level windows in the same application from the task bar. This can confuse end users, but it does not affect their work much, because all the hidden windows are modal blocked and cannot be operated.
When your application runs as an applet in a browser and shows a modal dialog, the browser window might become blocked. The implementation of this blocking varies in different browsers and operating systems. For example, on Windows, both Internet Explorer and Mozilla work correctly, and on Solaris OS and Linux, Mozilla windows are not blocked. This will be corrected in a future release.
The AWT Modality document for Java SE 6 describes the modality-related features and how to use them. One of the sections in this document describes some areas that might be related to or affected by modal dialogs: always-on-top property, focus handling, window states, and so forth. Application behavior in such cases is usually unspecified or depends on the platform; therefore, do not rely on any particular behavior.
This section first describes how to troubleshoot memory leaks. It then presents some possible sources of memory leaks and provides workarounds.
To get more information on a memory leak, execute java with the heap profiler active. Specify that the output should be generated in binary format so that you can use the jhat utility to read the output.
$
java -agentlib:hprof=file=snapshot.hprof,format=b
application
See the Troubleshooting Guide for Java SE 6 with HotSpot VM for more detailed information on troubleshooting memory leaks, as well as descriptions of the jhat utility and other troubleshooting tools that are available.
Issue: Memory leak in application.
Cause: Frames and Dialogs are sometimes not being garbage-collected. This bug will be corrected in a future version of Java SE.
Workaround: Known memory leaks occur in cases when the system starts to transfer focus to a focusable top-level element (window, dialog, frame), but the element is closed, hidden, or disposed of before the focus transfer is complete. Therefore, the application must wait for the focus transfer operation to finish before closing, hiding, or disposing of the element.
Note that this problem normally occurs only when these actions are performed programmatically, since the user typically cannot physically perform these actions fast enough to cause the problem.
This section describes how to determine if a crash is related to AWT, as well as how to troubleshoot such crashes.
When a crash occurs, an error log is created with information and the state obtained at the time of the fatal error. See
Appendix B, Fatal Error Log for detailed information about this log file.
A line near the top of the file indicates the library where the error occurred. The example below shows that the crash was related to the AWT library.
... # Java VM: Java HotSpot(TM) Client VM (1.6.0-beta2-b76 mixed mode, sharing) # Problematic frame: # C [awt.dll+0x123456] ...
However, the crash can happen somewhere deep in the system libraries, although still caused by AWT. In such cases the indication awt.dll does not appear as a problematic frame, and you need to look further in the file, in the section Stack: Native frames: Java frames. Below is an example.
Stack: [0x0aeb0000,0x0aef0000), sp=0x0aeefa44, free space=254k Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) C 0x00abc751 C [USER32.dll+0x3a5f] C [USER32.dll+0x3b2e] C [USER32.dll+0x5874] C [USER32.dll+0x58a4] C [ntdll.dll+0x108f] C [USER32.dll+0x5e7e] C [awt.dll+0xec889] C [awt.dll+0xf877d] j sun.awt.windows.WToolkit.eventLoop()V+0 j sun.awt.windows.WToolkit.run()V+69 j java.lang.Thread.run()V+11 v ~StubRoutines::call_stub V [jvm.dll+0x83c86] V [jvm.dll+0xd870f] V [jvm.dll+0x83b48] V [jvm.dll+0x838a5] V [jvm.dll+0x9ebc8] V [jvm.dll+0x108ba1] V [jvm.dll+0x108b6f] C [MSVCRT.dll+0x27fb8] C [kernel32.dll+0x202ed] Java frames: (J=compiled Java code, j=interpreted, Vv=VM code) j sun.awt.windows.WToolkit.eventLoop()V+0 j sun.awt.windows.WToolkit.run()V+69 j java.lang.Thread.run()V+11 v ~StubRoutines::call_stub
If the text awt.dll appears somewhere in the native frames, then the crash might be related to AWT.
Most of the AWT crashes occur on the Windows platform and are caused by thread races. Many of these problems were fixed in Java SE version 6, so if your crash occurred in an earlier release, first try to determine if the problem is already fixed in the latest release.
One of the possible causes of crashes is that many AWT operations are asynchronous. For example, if you show a frame with a call to frame.setVisible(true), then you cannot be sure that it will be an active window after the return from this call.
Another example concerns native file dialogs. It takes some time for the operating system to initialize and show these dialogs, and if you dispose of them immediately after the call to setVisible(true), then a crash might occur. Therefore, if your application contains some AWT calls running simultaneously or immediately one after another, it is a good idea to insert some delays between them or add some synchronization.
This section includes the following information:
How to trace focus events
Description of the focus system in the plugin
Focus models supported by X Window managers
Focus traversal
Miscellaneous problems that can occur with focus
To troubleshoot a problem with the focus, you can trace focus events. Start with just adding a focus listener to the toolkit, as shown here.
Toolkit.getDefaultToolkit().addAWTEventListener( new AWTEventListener(){
public void eventDispatched(AWTEvent e) {
System.out.println(e);
System.out.flush();
}
}, FocusEvent.FOCUS_EVENT_MASK | WindowEvent.WINDOW_FOCUS_EVENT_MASK | WindowEvent.WINDOW_EVENT_MASK);
The System.err stream is used here because it does not buffer the output.
Remember that the correct order of focus events is the following:
FOCUS_LOST on component losing focus
WINDOW_LOST_FOCUS on top-level losing focus
WINDOW_DEACTIVATED on top-level losing activation
WINDOW_ACTIVATED on top-level becoming active widow
WINDOW_GAINED_FOCUS on top-level becoming focused window
FOCUS_GAINED on component gaining focus
When focus is transferred between components inside the focused window, only FOCUS_LOST and FOCUS_GAINED events should be generated. When focus is transferred between owned windows of the same owner or between an owned window and its owner, then the following events should be generated:
FOCUS_LOST
WINDOW_LOST_FOCUS
WINDOW_GAINED_FOCUS
FOCUS_GAINED
Note that events of losing focus or activation should come first.
Sometimes a problem may be caused by the native platform. To check this, investigate the native events that are related to focus. Make sure that the window you want to be focused gets activated and the component you want to focus receives the native focus event.
On the Windows platform, the native focus events are the following:
WM_ACTIVATE for a top-level. WPARAM is WA_ACTIVE when activating and WA_INACTIVE when deactivating.
WM_SETFOCUS and WM_KILLFOCUS for a component.
On the Windows platform, in some cases a component that is the focus owner might not correspond to the component on which the native system set focus. This occurs when the focus is set by synthesizing a focus event. Nevertheless, such a focus owner is painted like a normally focused component. A lightweight component is focused by synthesizing a focus event, whereas its nearest heavyweight component is focused in the normal way. A heavyweight component can also have “synthetic focus,” for example, the focus owner in an owned window (not a frame or a dialog). In this case native focus is set on a special component, called a “focus proxy.” inside the owner. A focus proxy component is not visible to the user and is used only at the native level. This mechanism allows AWT to separate active and focused windows. However, with the focus proxy, tracking the flow of native focus events can become complicated.
On Solaris OS and Linux, XToolkit uses a focus model that allows AWT to manage focus itself. With this model the window manager does not directly set input focus on a top-level window, but instead it sends only the WM_TAKE_FOCUS client message to indicate that focus should be set. AWT then explicitly sets focus on the top-level window if it is allowed.
Note that X server and some window managers may nevertheless send focus events to a window. However all such events are discarded by AWT.
AWT does not generate the hierarchical chains of focus events when a component inside a top-level gains focus. Moreover, the native window mapped to the component itself does not get any native focus event. On the Solaris OS and Linux platforms, as well as on the Windows platform, AWT uses the focus proxy mechanism. Therefore, focus on the component is set by synthesizing a focus event, whereas the invisible focus proxy has native focus.
A native window that is mapped to a Window object (not a Frame or Dialog object) has the override-redirect flag set. Thus the window manager does not notify the window about focus change. Focus is requested on the window only in response to a mouse click. This window will not receive native focus events at all. Therefore, you can trace only FocusIn or FocusOut events on a frame or dialog. Since the major processing of focus occurs at the Java level, debugging focus with XToolkit is simpler than with WToolkit.
An applet is embedded in a browser as a child (though not a direct child) of an EmbeddedFrame. This is a special Frame that has the ability to communicate with the plugin. From the applet's perspective the EmbeddedFrame is a full top-level Frame. Managing focus for an EmbeddedFrame requires special additional actions. When an applet first starts, the EmbeddedFrame does not get activated by default by the native system. The activation is performed by the plugin that triggers a special API provided by the EmbeddedFrame. When focus leaves the applet, the EmbeddedFrame is also deactivated in a synthesized manner.
It could happen that a lightweight component does not gain focus but the nearest heavyweight does instead. This is due to the native system setting focus on it by itself, bypassing AWT. To work around this problem, set a focus listener to the heavyweight and retransfer focus on the lightweight when necessary.
The following focus models are supported by X window managers:
click-to-focus is a commonly used focus model. (For example, Microsoft Windows uses this model.)
focus-follows-mouse is a focus model in which focus goes to the window that the mouse hovers over.
The focus-follows-mouse mode is not detected in XAWT in Java SE 6, and this causes problems for simple windows (objects of java.awt.Windowclass). Such windows have the override-redirect property, which means that they can be focused only when the mouse button is pressed, and not by hovering over the window. As a workaround, set MouseListener on the window and request focus on it when mouse crosses the window borders.
Sometimes a problem occurs when some object is not traversable. For example, LayoutFocusTraversalPolicy, which is the Swing focus traversal policy (FTP), implicitly transfers focus down-cycle. The focus specification says the following:
During normal forward focus traversal, the Component traversed after a focus cycle root will be the focus-cycle-root's default Component to focus.
However when you transfer focus from some component to a focus cycle root container (for example, a container inside another focus cycle root), the container itself will not get focus and focus will not be transferred down-cycle into the container.
This behavior will be changed in a future release. However, in the Java SE 6 release you can easily change this behavior. First, make the focus cycle root container traversable itself, for example by calling setFocusable(true) on the container. Then by default it will become the default component to focus (because it would be the first component in its cycle). You have to set the default component in the cycle implicitly, as follows:
theContainer.setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() {
public Component getDefaultComponent(Container root) {
return theComponent;
}
});
Now you have your focus cycle traversable. However, because you made the container focusable, it gains focus first when you move to the cycle, and it looks like focus has disappeared. To avoid this behavior you can add FocusListener to your container, as follows:
theContainer.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
theContainer.getFocusTraversalPolicy().
getDefaultComponent(theContainer).requestFocusInWindow();
}
});
In this way focus will be transferred to the default component in the container's cycle.
This section describes some issues that can arise with focus in AWT and suggests solutions.
Clicking a component inside a frame causes focus to change.
Solution: Check the version of your window manager and upgrade it to 3.0 or greater.
Solution: To catch traversal key events, you must enable them by calling Component.setFocusTraversalKeysEnabled(boolean).
The frame, its owner, is modal blocked. In this case the window will also remain modal blocked.
Solution: A window cannot become the focused window when its owner is not allowed to get focus. The solution is to exclude the owner from modality.
The window does not receive WINDOW_GAINED_FOCUS, but the currently focused window receives WINDOW_LOST_FOCUS. Moreover, the window gains native focus (that is, its title is highlighted), but neither the window nor its components can get key events.
Solution: This behavior is specific to dtwm. The only way to avoid this problem is to switch to JDS.
Sometimes java.lang.NullPointerException: null pData is thrown.
Solution: The easiest way to avoid throwing the exception is to do the removal along with requesting focus on EDT. Another, more complicated, approach is to synchronize requesting focus and removal if you need to perform these actions on different threads.
Solution: In order not to lose focus completely, you can request it on, for example, the default component of the current focus cycle root (the parent of the container) after the container is removed.
For example, Component A is the focus owner. Focus is requested on Component B, and immediately after this Component A is removed from its container. Eventually focus goes to Component C, which is located after Component A in the container, but not to Component B.
Solution: In this case, ensure that the requesting focus is executed after Component A is removed, not before.
For example, a frame is displayed, with a window that it owns. The frame is inactive, so the window is not focused. Then the window is set to alwaysOnTop. The window gains focus, but its owner remains inactive. Therefore, the window cannot receive key events.
Solution: Bring the frame to front ( Frame.toFront() method) before setting the window to alwaysOnTop.
Solution: Bring the frame to front ( Frame.toFront() method) after showing it ( Frame.setVisible(true) method).
For example, a frame is the focused window, and one of its components is the focus owner. Another window is clicked, and then the frame is clicked again. WINDOW_GAINED_FOCUS comes to the frame and the WindowFocusListener.windowGainedFocus(WindowEvent) method is called. However, inside of this callback you cannot determine the frame's most recent focus owner, because Frame.getMostRecentFocusOwner() returns null.
Solution: You can get the frame's most recent focus owner inside the WindowListener.windowActivated(WindowEvent) callback. However, by this time the frame will have become the focused window only if it does not have owned windows. Note that this approach does not work for the window, only for the frame or dialog.
Solution: This behavior is the default since JDK 1.3. However you might need to prevent the applet from getting focus on startup, for example, if your applet is invisible and does not require focus at all. In this case, you can set to false the special parameter initial_focus in the HTML tag, as follows:
<applet code="MyApplet" width=50 height=50> <param name=initial_focus value="false"> </applet>
Solution: Do not assume that the condition set by calling Component.setEnabled(false) or Component.setFocusable(false) will be maintained unfocusable along with all its content. Instead, use the Window.setFocusableWindowState(boolean) method.
This section discusses possible problems with Drag and Drop and the clipboard.
It is difficult to use a debugger to troubleshoot Drag and Drop, because during the drag–and–drop operation all input is grabbed. Therefore, if you place a breakpoint during drag–and–drop, you might need to restart your X server. Try to use remote debugging instead.
Two simple methods can be used to troubleshoot most issues with Drag and Drop:
Printing all DataFlavor instances
Printing received data
An alternative to remote debugging is the System.err.println() function, which prints output without delay.
This section describes some issues that frequently arise with Drag and Drop in AWT and suggests troubleshooting solutions.
Using the Clipboard.getContents() function for a paste operation sometimes causes the application to hang for a while, especially if a rich application provides the data to paste.
The Clipboard.getContents() function fetches clipboard data in all available flavors (for example, some text and image flavors), and this can be expensive and unnecessary.
Solution: Use the Clipboard.getData() method to get only specific data from the clipboard. If data in only one or a few flavors are needed, use one of the following Clipboard methods instead of getContents():
DataFlavor[] getAvailableDataFlavors()
boolean isDataFlavorAvailable(DataFlavorflavor)
Object getData(DataFlavorflavor)
In order to initialize transferred data only if it is needed, initialization code was put in Transferable.getTransferData().
Transferable data is expensive to generate, and during a DnD operation Transferable.getTransferData() is invoked more than once, causing a slowdown.
Solution: Cache the Transferable data so that is generated only once.
On Windows and some window managers, transferred file lists can be represented as DataFlavor.javaFileListFlavor data flavor. But not all window managers represent lists of files in this format. For example, the GNOME window manager represents a file list as a list of URIs.
Workaround: To get files, request data of type String, and then translate the string to a list of files according to text/uri-list format described in RFC 2483. To enable dropping files from a Java application to GNOME/KDE desktop and file browser, export data in the text/uri-list format. For a code example, see the Work Around section of this bug report:
Solution:Move a Window with an image rendered on it as the mouse cursor moves during a DnD operation. See the code example in the Work Around section of the following RFE:
The DataFlavor class has no constructor which handles arrays. The mime type for array contains characters which should be escaped. For example, the following code throws an IllegalArgumentException:
new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + "; class=" + (new String[0]).getClass().getName())
Solution: Quote the value of the representation class parameter, as shown in the following code, where the quotation marks are escaped:
new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + "; class=" + "\"" + (new String[0]).getClass().getName() + "\"")
For more information, see the following bug report:
Various problems can arise, for example, odd events are fired during a DnD operation, multiple items cannot be dragged and dropped, an InvalidDnDOperationException is thrown.
Solution: Use Swing's DnD support with Swing components. Although the Swing DnD implementation is based on the AWT DnD implementation, you cannot mix Swing and AWT drag–and–drop.
In order to change the state of the source to depend on the target, you need to have references to the source and target components in the same area of code, but this is not currently implemented in the Drag and Drop API.
Workaround: One workaround is to add flags to the transferable object that allow you to determine the context of the event.
For the transfer of data within one Java VM, the following workaround is proposed:
Implement your target component as DragSourceListener.
In DragGestureRecognizer.dragGestureRecognized() add the target at drag source listener, as follows:
public void dragGestureRecognized(DragGestureEvent dge) {
dge.startDrag(null, new StringSelection("SomeTransferedText"));
dge.getDragSource().addDragSourceListener(target);
}
Now you can get the target and the source in the dragEnter(), dragOver(), dropActionChanged(), and dragDropEnd() methods of DragSourceListener().
The transferring of a big bundle of data or the creation of transferred objects takes too long. The user must wait a long time for the data transfer to complete.
This expensive operation makes transferring too long because you must wait until Transferable.getTransferData() finishes.
Solution: This solution is valid only for transferring data within one Java VM. Create or get expensive resources before the drag operation. For example, obtain file content when you create transferable, so that Transferable.getTransferData() will not be too long.
This section describes other issues in troubleshooting AWT.
This section describes some issues that can arise with the splash screen in AWT with the Java SE 6 release, and suggests solutions.
Solution: See next solution.
Solution: The splash screen image will be picked from a jar file only if the jar file is used with the -jar command line option. This jar file should contain both the “SplashScreen-Image” manifest option and the image file. Jar files in -classpath will never be checked for splash screens in MANIFEST.MF. If you do not use -jar, you can still use -splash to specify the splash screen image in the command line.
Solution: This is a native limitation of X11. On Solaris OS and Linux, the alpha channel of a translucent image will be compared with 50% threshold. Alpha values above 0.5 will make opaque pixels and pixels with alpha below 0.5 completely transparent. Translucency support might improve in future versions of Java SE.
With the Java SE 6 release on the Windows 98 platform, the method TrayIcon.displayMessage() is not supported because the native service to display a balloon is not supported on Windows 98.
If a SecurityManager is installed, the value of AWTPermission must be set to accessSystemTray in order to create a TrayIcon object.
In the JPopupMenu.setInvoker() method, the invoker is the component in which the popup menu is to be displayed. If this property is set to null, the popup menu does not function correctly.
The solution is to set the popup's invoker to itself.
Many AWT components use their own defaults for background and foreground colors instead of using the colors of their parents.
This behavior is platform-dependent: the same component can behave differently on different platforms. In addition, some components use the default value for one of the background or foreground colors, but take the value from the parent for another color.
To ensure the consistency of your application on every platform, use explicit color assignment (both foreground and background) for every component or container.
The AWT Container has a size limitation. On most platforms, this limit is 32767 pixels. This means that, for example, if the canvas objects are 25 pixels high, a Java AWT panel cannot display more than about 1400 objects.
Unfortunately there is no way to change this limit, either with Java code or with native code. The limit depends on what data type the operating system uses to store a widget size. For example, the Windows 2000/XP operating system and the Linux X operating system use integer type and are therefore limited to the maximum size of an integer. Other operating systems might use different types, such as long, and in this case the limit could be higher.
Refer to the documentation for your platform for information.
The following are examples of workarounds for this limit that might be helpful:
Display components page by page.
Use tabs to display a few components at a time.
|
Copyright ©1995, 2010, Oracle and/or its affiliates. All rights reserved. Legal Notices
|
|