Incompatible Changes in the 1.1 AWT API

As a rule, code written for the 1.0, 1.0.1, and 1.0.2 releases can be compiled without change in the 1.1 release (although you might see some warnings about "deprecated" API). Also, code compiled under those earlier releases generally works (without recompilation) at least as well in a 1.1 runtime system as it did before. This document lists the AWT exceptions to these rules -- the changes that might cause incompatible compilation or runtime behavior. For information about non-AWT JDK 1.1 compatibility, see JDK 1.1 Compatibility with Previous JDK Releases.

Here are the incompatible AWT changes:

  1. On Windows 95/NT systems, menus no longer allow keyboard alternatives, known as mnemonics. Due to an implementation flaw, you used to be able to specify mnemonics in Windows 95/NT by putting an ampersand ("&") in the menu label. For example, a menu item with the label "Save &As..." defined "a" as the mnemonic and would result in "A" being underlined in the displayed menu item -- but only on Windows 95/NT. Now, menus with "&" in the label simply display the "&" on Windows 95/NT, as they always have on other platforms. The reason the "&" hack no longer works is that it depended on the AWT using the native menu system, which it no longer does due to the need to support modifiable fonts and the display of non-Latin1 text. We plan to add support for menu mnemonics in a future release.

  2. On Windows 95/NT systems, canvases and panels might seem unable to get keyboard events. The reason is that they no longer automatically get the focus, which is required for receiving keyboard events. To give a canvas or panel the focus, use the requestFocus method. For example, your implementation of the mouseClicked method in the MouseListener for a custom component should invoke the requestFocus method on the component.

  3. The following four 1.0.2 methods in the java.awt.peer package have been removed in 1.1: Note: API in the java.awt.peer package is always subject to change because the peer classes aren't intended to be called directly by developers.

  4. Trying to add a window to a container now results in an IllegalArgumentException.

  5. The Graphics drawPolygon method used to draw unclosed polygons if the end point wasn't the same as the start point. In 1.1, drawPolygon automatically closes the polygon. If you want to draw an unclosed polygon, you can use the new drawPolyline method instead.

  6. Constructors for the Color class now check the range of the parameters passed in, and throw an IllegalArgumentException if out-of-range values are encountered.

  7. Passing a null frame to a Dialog constructor now results in an IllegalArgumentException.

  8. The public abstract method nextFocus has been removed from the java.awt.peer.ComponentPeer interface. This does not affect applications or applets, since the peer interfaces are private interfaces between the AWT and its implementations.

  9. Bug fixes in Win32 event handling might mean that your components get more events than they used to. Details are in the Improvements in Win32 Event Handling section below.

  10. The synchronization model of the AWT has been revised to reduce the potential of deadlock. This might result in different behavior of existing programs. Details are in the Details of the New Synchronization Model section below.

  11. In the CheckBoxMenuItem class, the object argument of the action() method has changed. In the 1.02 release the object argument was the label of the checkbox menu item, but in the 1.1 release the object argument is the state of the checkbox menu item.

Improvements in Win32 Event Handling

Many bugs were fixed in the event handling of the win32 implementation of the AWT. In particular, focus events were previously not delivered to certain components (buttons, etc.) in 1.0.2, but are now properly delivered on win32 in 1.1. If you have a handleEvent method which is not coded properly to handle these new events, you may see changes in the way your program runs. For example, if you had the following fragment in the handleEvent method of a Frame:
if (event.id == Event.GOT_FOCUS) {
    // do something...
}
This block will now be called when components within the Frame (such as buttons) get the focus. If the block isn't designed to handle this case, then your program may not run as it did in 1.0.2.

Details of the New Synchronization Model

The synchronization model of the AWT has been revised to significantly reduce (but not eliminate) the potential of deadlock that existed in the 1.0.2 JDK. This is not, strictly speaking, an incompatibility with previous releases, but it does have the potential to change the behavior of existing programs. The AWT never was, and still isn't, guaranteed to be free of race conditions or deadlocks, given all the ways it can be invoked from and subclassed by client code.

In the new synchronization model, the structure and layout of components inside containers is guarded by a single AWT-wide lock, using an object called Component.LOCK, declared as follows in the Component class:

public static final Object LOCK = new Object();

For example, Container.validate, Container.add, and Container.remove all contain synchronized blocks that use Component.LOCK.

Setter methods for individual component state, such as Component.setEnabled or Button.setLabel, are synchronized on the instance itself. Getter methods are generally not synchronized, but they are semi-guarded by the copy-to-stack strategy: a thread-local copy of shared data is made and then used in the method.

Code that uses the AWT should be carefully scrutinized for uniform locking order if it acquires locks of its own while overriding an AWT method invoked in a synchronized context. For example, if you acquire your own locks in your layout code, you have to be aware that this code is being called with the Component.LOCK lock already held. If your code in another thread holds your lock and then tries to invoke validate, your program can deadlock. When you identify cases like this, you should rewrite your code wherever possible to ensure a uniform locking order. This order is usually client lock first, then Component.LOCK.


Feedback to Kathy Walrath