1.1 AWT API の非互換変更

概して、 1.0、1.0.1、1.0.2 バージョン用に書かれたコードは、変更なしに 1.1 バージョンでコンパイルできます (ただし、「推奨されない」API に関する警告が表示される可能性はあります)。また、これら以前のバージョンでコンパイルされたコードは、(再コンパイルなしで) 通常、前と同様に 1.1 実行システムでも最低動作はします。このドキュメントでは、これら規則に対する AWT の例外、すなわち互換性のないコンパイルまたは実行動作を生じる変更を説明します。非 AWT JDK 1.1 の互換性については、 JDK 1.1と以前の JDKリリースとの互換性を参照してください。

次に、互換性のない AWT 変更を示します:

  1. Windows 95/NT システムのメニューでは、もはやニーモニックとして知られるキーボード代替を許しません。実装の欠陥から、Windows 95/NT ではメニューラベルにアンパサンド("&")を付けてニーモニックを指定することができました。例えば、"Save As..." というラベルのメニュー項目が "a" をニーモニックとして定義したとすると、表示されたメニュー項目には "A" に下線を付けられました。しかしこれは Windows 95/NT 上でだけでした。現在では、ラベルに "&" の付いたメニューは、 Windows 95/NT 上でも他のプラットフォームと同様に "&" を表示するだけです。"&" ハックがもはや機能しないのは、これがネイティブメニューシステムを使用して AWT に依存していたためです。このメニューシステムは、修正可能なフォントと非 Latin1 テキストをサポートする必要から、それを止めたのです。将来のバージョンアップでは、メニューニーモニックのサポートを追加する予定です。

  2. Windows 95/NT システムでは、キャンバスとパネルはキーボードイベントを取得できないように見えるかもしれません。それは、キーボードイベントを受け取るために必要なフォーカスを自動的に取得できないことによります。キャンバスやパネルにフォーカスを与えるためには、requestFocus メソッドを使用します。例えば、MouseListener の中の mouseClicked メソッドをカスタムコンポーネント用に実装する場合、そのコンポーネントの requestFocus メソッドを起動する必要があります。

  3. java.awt.peer パッケージの次の 4 つの 1.02 メソッドは、1.1では除外されています: 注: peer クラスを、開発者が直接呼び出すことは意図していないため、java.awt.peer パッケージの API は常に変更される可能性があります。

  4. ウィンドウをコンテナに追加しようとすると、現在では IllegalArgumentException となります。

  5. 終点が開始点と同じでない場合、GraphicsdrawPolygon メソッドは、閉じない多角形を描画していました。 1.1 では、drawPolygon は自動的に多角形を閉じます。閉じない多角形を描画したい場合は、代わりに新しい drawPolyline メソッドを使用することができます。

  6. Color クラスの構築子は、渡されるパラメータの範囲をチェックし、範囲外の値を見つけた場合、IllegalArgumentException をスローします。

  7. Dialog 構築子に null フレームを渡すと、現在では IllegalArgumentException となります。

  8. public abstract メソッド nextFocus は、 java.awt.peer.ComponentPeer インタフェースから除外されました。ピアインタフェースは AWT とその実装との間の private インタフェースであるため、これはアプリケーションやアプレットには影響しません。

  9. Win32 イベント処理のバグ修正をすると、使用しているコンポーネントが従来以上のイベントを取得する可能性があります。詳細については、後節の Win32 イベント処理の改善を参照してください。

  10. AWT の同期モデルは、デッドロックの可能性を削減するために改訂されました。これで、既存のプログラムが異なる動作をする可能性がでてきます。詳細については、後節の新しい同期モデルの詳細を参照してください。

Win32 イベント処理の改善

AWT の Win32 実装のイベント処理では、たくさんのバグが修正されました。特に、フォーカスイベントは以前は 1.0.2 の一部のコンポーネント (ボタンなど) に送られませんでしたが、今では 1.1 の Win32 上に正しく送られます。これらの新しいイベントを正しく処理するコード化がなされていない handleEvent メソッドを持っている場合、プログラムの動作状態を見て変更点が分かるでしょう。FramehandleEvent メソッドに次のフラグメントを持っている場合を示します:
if (event.id == Event.GOT_FOCUS) {
    // do something...
}
Frame 内のコンポーネント (ボタンなど) がフォーカスを取得したとき、このブロックが呼び出されます。ブロックがこのようなケースを処理するように設計されていない場合、プログラムは 1.0.2 のときのように動作しない可能性があります。

新しい同期モデルの詳細

AWTの同期モデルは、1.0.2 JDK に存在したデッドロックの可能性を、(皆無にはしないにしても) 著しく削減 するために、改訂されました。厳密にいえば、これは前のバージョンとの非互換ではありませんが、既存のプログラムの動作が変わる可能性があります。クライアントコードで起動およびサブクラス化ができる以上、AWT に競合状態やデッドロックがないという保証は、かつても今もありえません。

新しい同期モデルでは、コンテナ内のコンポーネントの構造とレイアウトは、単一の AWT 全体ロックによって保護されています。これには、Component クラスで次のように宣言した Component.LOCK と呼ばれるオブジェクトが使用されます。

public static final Object LOCK = new Object();

例えば、Container.validateContainer.add、 および Container.remove には、Component.LOCK を使用する同期化ブロックがすべて含まれています。

Component.setEnabled または Button.setLabel などの個別コンポーネント状態に対する Setter メソッドは、インスタンス自身の上で同期化されます。 Getter メソッドは通常同期化されませんが、共有データのスレッドローカルコピーを作り、このメソッドで使用するというコピー貼り付け方式によって、半ば保護されています。

AWT を使用するコードについて、それが同期化コンテキストで起動された AWT メソッドをオーバーライドする間に自分自身のロックを獲得する場合、一定のロック順序に関する綿密な調査を行う必要があります。例えば、レイアウトコード内で自分のロックを獲得する場合、このコードが既に保持されている Component.LOCK ロックで呼び出されることを認識しておく必要があります。他のスレッドのコードがロックを保持し、 validate を起動しようとする場合、プログラムがデッドロックする可能性があります。このようなケースを識別したとき、一定のロック順序を保証するために、可能なところでコードを書き直す必要があります。この順序は通常クライアントロックを最初にし、次に Component.LOCK がきます。


フィードバックは Kathy Walrath 宛てに送ってください。