この章では、さまざまな Java SE クライアントテクノロジ間の相互作用について説明します。この章ではさらに、問題のトラブルシューティングの開始場所となるテクノロジをユーザーが特定するための手助けをします。
Java SE デスクトップは、Java SE デスクトップの概要に関するサイトで説明しているいくつかのテクノロジから構成されます。このガイドでは現在のところ、次のデスクトップテクノロジのトラブルシューティング手順について説明しています。
AWT
Java 2D
Swing
国際化
Java Sound
Java Plug-in
このセクションでは、さまざまなデスクトップテクノロジ間の相互作用について説明します。また、ネイティブコードと連携して動作したり、ハードウェア構成やソフトウェア構成などの環境に依存したりする可能性の高いテクノロジについても説明します。
これらのテクノロジ間の関係の理解が深まるほど、問題が属する分野をすばやく特定できるようになります。
Java SE デスクトップの Java テクノロジは、リッチクライアントアプリケーションおよびアプレットを作成するために使用されます。デスクトップツールおよびライブラリは、プラットフォームのコアツールおよびライブラリとのインタフェースを備えています。
Abstract Window Toolkit (AWT) は、グラフィカルユーザーインタフェース (GUI) プログラミングをサポートします。この API は、開発者に次の機能を提供します。
メニュー、ボタン、テキストフィールド、ダイアログボックス、チェックボックスなどのコンポーネントの構築
これらのコンポーネント経由でのユーザー入力の処理
楕円や多角形など、単純な形状のレンダリング
アプリケーションで使用されるユーザーインタフェースのレイアウトやフォントの制御
ネイティブのドラッグ&ドロップ、イベント、およびカーソルの処理
これらのクラスはソフトウェアスタックの最下部 (ベースとなるオペレーティングシステムやデスクトップシステムにもっとも近い位置) にあります。
AWT は一連の重量コンポーネントも提供します。
純粋な AWT アプリケーションは通常、Swing に関係しません。AWT アプリケーションでカスタムレンダリングを行う場合は、Java 2D が使用されます。
Java 2D API は、2 次元の高度なグラフィックスとイメージングを処理するクラスの集まりです。この API は、AWT のグラフィックス、テキスト、およびイメージング機能を拡張します。
Java 2D もソフトウェアスタックの最下部 (ベースとなるオペレーティングシステムやデスクトップシステムにもっとも近い位置) にあります。
Swing クラスは AWT と Java 2D のアーキテクチャーの上に構築されています。Swing には、GUI を構築し、Java アプリケーションに豊富なグラフィックス機能や対話処理を追加するための一連のコンポーネントが実装されており、プラグイン可能な Look & Feel 機能も備えています。
Swing は軽量ツールキットなので、ネイティブプラットフォームとの対話処理はほとんどありません。Swing はレンダリングに Java 2D を使用し、AWT が Window、Frame、Dialog などのトップレベルコンポーネントの作成および操作機能を提供します。
国際化とは、技術的な変更をせずにソフトウェアをさまざまな言語および地域に適合させるための、アプリケーションの設計プロセスのことです。
Java Sound は、オーディオおよび MIDI (Musical Instrument Digital Interface) データのキャプチャーや処理、再生といった、サウンド処理の入力と出力を制御するための低レベルの API を提供します。
Java Plug-in は、Web ブラウザの機能を拡張し、アプレットや Java Beans を、Web ブラウザ付属の Java 実行環境でなく、Java SE 実行環境 (JRE) で実行可能にします。
次のリストは、問題のトラブルシューティングに役立つ可能性のあるアドバイスを示したものです。
症状を特定します。
問題のタイプを特定します。
問題の分野を見つけます。
関連する構成情報を記録します。
問題以外を除去します。
正しいパッチ、ドライバ、およびオペレーティングシステムがインストールされていることを確認します。
以前のリリースを試します (バックトレース)。
テストを最小化します。一度にテストする問題の数をできるだけ制限します。
ハードウェアおよびソフトウェアの構成を最小化します。単一システムや複数システム上で問題を再現できるかを確認します。ブラウザのバージョンによって問題が変化するかを確認します。
VM が複数インストールされているかどうかに問題が依存するかを確認します。
原因を見つけます。
その分野での典型的な原因をチェックします。
フラグを使ってデフォルトを変更します。
トレースを使用します。
例外的な場合には、システムプロパティーを使ってペイントシステムの動作を一時的に変更します。未サポートのいくつかのプロパティーについては、Java 2D テクノロジのシステムプロパティーに関するページを参照してください。
修正を見つけます。
可能性のある回避方法を見つけます。
設定を修正します。
バグを提出します。
ユーザーのアプリケーションを修正します。
HotSpot VM に関する Java SE 7 向けのトラブルシューティングガイドでは、Java SE アプリケーションと Java HotSpot 仮想マシン間の問題のトラブルシューティングに役立つ可能性のある情報を提供しています。この情報の多くは、Java SE デスクトップテクノロジを使用したアプリケーションの問題にも適用できます。
レポートの提出方法に関する指針や、レポートで収集すべきデータに関する提案については、第 8 章「バグレポートの提出」を参照してください。
時間を取って、発生している問題を分類してください。そうすれば、問題の特定分野の識別、原因の発見、および最終的な解決方法や回避方法の決定が容易になります。これらの問題の中には明確でないものもありますが、すべての可能性を検討することや問題でない要素を除外することは、常に役立ちます。
クラッシュが発生すると、致命的エラーの発生時に取得された情報や状態を含むエラーログが作成されます。エラーログファイルのデフォルト名は、hs_err_pidpid.log です。このファイルは、スタンドアロン Java アプリケーションの場合は現在のディレクトリに作成され、Java アプレットの場合はブラウザバイナリディレクトリまたはユーザークライアントフォルダに作成されます。
致命的エラーログの詳細説明については、付録 B「致命的エラーログ」を参照してください。
ヘッダーセクションの先頭付近の行には、エラーが発生したライブラリが示されます。下の例では、クラッシュが AWT ライブラリに関係していたことがわかります。
... # Java VM: Java HotSpot(TM) Client VM (1.6.0-beta2-b76 mixed mode, sharing) # Problematic frame: # C [awt.dll+0x123456] ...
クラッシュが JNI ネイティブコードで発生した場合、その原因はおそらくデスクトップライブラリです。ネイティブライブラリでのクラッシュは通常、Java 2D または AWT での問題を意味しますが、それは、Swing にはネイティブコードがあまり含まれていないからです。Swing に含まれる少量のネイティブコードのほとんどはネイティブ Look & Feel に関するものなので、アプリケーションでネイティブ Look & Feel が使用されている場合はこの分野に関するクラッシュである可能性があります。
エラーログでは通常、クラッシュが発生した具体的なライブラリが示されるため、この情報から原因を推測できます。JDK の一部でないライブラリでのクラッシュは通常、環境の問題 (不正なビデオドライバやデスクトップマネージャーなど) を示しています。
VM がクラッシュする場合は、HotSpot VM に関する Java SE 7 向けのトラブルシューティングガイドを参照してください。
パフォーマンスの問題は、得られる情報が一般にあまり多くないため、診断が難しくなります。
まず、どのテクノロジで問題が発生しているかを判断する必要があります。たとえば、レンダリングパフォーマンスの問題はおそらく Java 2D の中にあり、応答性の問題は Swing に関連します。
次に、パフォーマンス関連の問題の例をいくつか示します。
起動。アプリケーションが起動してユーザーが使える状態になるまで、どれくらいの時間がかかりますか。
フットプリント。アプリケーションのメモリー使用量はどれくらいですか。これを測定するには、Windows ではタスクマネージャー、Solaris OS および Linux では top や prstat などのツールを使用します。
実行時のパフォーマンス。アプリケーションは、実行するように設計されたタスクをどれくらいの速度で完了しますか。たとえば、アプリケーションが何かを計算する場合、その計算が完了するまでどれくらいの時間がかかりますか。ゲームの場合、フレームレートは許容範囲ですか。アニメーションはスムーズに見えますか。
これは、次のトピックの応答性と同じではありません。
応答性。アプリケーションがユーザーとの対話に応答する速度はどれくらいですか。ユーザーがメニューをクリックした場合、メニューが表示されるまでどれくらいの時間がかかりますか。実行時間の長いタスクに割り込むことはできますか。アプリケーションの再ペイント速度は、アプリケーションの動作が遅く見えない程度に高速ですか。
クラッシュのほかに、動作に関係するさまざまな問題が発生する可能性があります。このセクションでは、それらの問題をいくつか取り上げ、トラブルシューティングの対象となる Java SE デスクトップテクノロジを示すことを試みます。
ハングアップ:アプリケーションがユーザー入力に応答しません。HotSpot VM に関する Java SE 7 向けのトラブルシューティングガイドの、ハングアップまたはループしているプロセスに関する章を参照してください。
Java コードでの例外。例外は、コンソール上やアプリケーションログファイル内に目に見えるかたちでスローされます。この出力を調べれば問題の分野がわかります。
レンダリングや再ペイントの問題。たとえば、あるアプリケーションの外観が、そのアプリケーション上に別のアプリケーションをドラッグしたことによって発生した再ペイント後におかしくなることがあります。その他の例として、不適切なフォント、間違ったカラー、スクロール、あるアプリケーションのフレーム上に別のウィンドウをドラッグしたことによってアプリケーションのフレームが破損する問題、破損した領域の更新、などが挙げられます。これらの問題は、Java 2D の問題、場合によっては Swing の問題を示します。
アプリケーションで再ペイントの問題が発生する場合、その問題はおそらく Java 2D または Swing に関連します。
簡単なテスト方法を次に示します。問題が別のプラットフォーム上で再現可能な場合 (たとえば、最初に Windows 上で確認された問題が Solaris OS や Linux 上でも存在する場合)、それは Swing の PaintManager の問題である可能性が非常に高くなります。
Java 2D のレンダリングパイプラインをいくつかのフラグで変更する方法については、第 3 章「Java 2D」のトラブルシューティングを参照してください。これは、問題が Java 2D、Swing のどちらに関係しているかを判断する際にも役立つ可能性があります。
マルチ画面に関する再ペイント問題 (ある画面から別の画面にウィンドウを移動した際の再ペイントの問題や、デフォルト以外の画面デバイスとの対話処理に起因するその他の異常な動作など) は、Java 2D に属します。
デスクトップの対話処理に関連する問題は、AWT の問題を示します。
デスクトップの対話処理に関連する問題のいくつかの例として、ウィンドウのサイズ変更、ウィンドウの最小化や最大化、フォーカス処理の問題、モーダリティー、システムトレイやスプラッシュ画面、画面上でのウィンドウ配置、複数画面の処理 (列挙) などが挙げられます。
ドラッグ&ドロップの問題。ドラッグ&ドロップは AWT に属します。
印刷の問題。これは、使用される API に応じて Java 2D、AWT のいずれかになります。
フォントの問題。
AWT アプリケーションのフォントレンダリングの問題は、おそらくフォントプロパティーまたは国際化の問題です。
ただし、アプリケーションで AWT のみが使用されている場合、テキストレンダリングの問題は Java 2D に起因している可能性があります。Solaris OS または Linux の場合、テキストレンダリングは Java 2D によって実行されます。あるいは、問題が AWT または国際化に属する可能性もあります。
ペイントの問題。これは通常、Swing の問題です。
テキストレンダリングの品質。
Swing のテキストレンダリングは Java 2D によって実行されます。したがって、Swing を使用したアプリケーションでテキストレンダリングの問題 (グリフの欠落、グリフの不正なレンダリング、行間や文字間の間隔の異常、フォントの低品質なレンダリングなど) が発生する場合、その問題はおそらく Java 2D に属します。
フルスクリーンの問題。これは Java 2D API です。
エンコーディングやロケールの問題 (ロケール固有の文字が表示されないなど) は、国際化の問題を示します。
このセクションでは、トラブルシューティングに役立つ可能性のある、いくつかのツールの一覧を単に示します。HotSpot VM に関する Java SE 7 向けのトラブルシューティングガイドには、これらのツールの大部分やその他の多くの有用なツールに関する詳細情報が含まれています。
パフォーマンス:ベンチマーク、プロファイラ、DTrace、Java プローブ
フットプリント:jhat、jmap、プロファイラ
クラッシュ:ネイティブデバッガ
ハングアップ:JConsole、jstack、ctrl + break
不正フォントのチェック:Font2DTest (JDK に付属。demo/jfc/Font2DTest)
また、さまざまな問題で dev.java.net の JDK ビルドをデバッグすることもできます。
JDWP (Java Debugging Wire Protocol) は、アプリケーションやアプレットのデバッグに非常に役立ちます。
アプリケーションをデバッグするには、次の手順を実行します。
コマンド行ウィンドウを開きます。PATH 環境変数を jdk/bin に設定します。
デバッグ対象の Java プログラム (この例では Test という名前) を次のように実行します。
Windows の場合:
java -Xdebug -Xrunjdwp:transport=dt_shmem,address=debug,server=y,suspend=y Test
Solaris OS および Linux の場合:
java -Xdebug -Xrunjdwp:transport=dt_socket,address=8888,server=y,suspend=y Test
Test クラスがデバッグモードで開始され、デバッガからの接続を待ちます。
Java レベルのデバッグを行うには、別のコマンド行ウィンドウを開き、上の実行中のデバッグサーバーにアドレス debug (Windows) または 8888 (Solaris OS または Linux) で接続するように jdb を実行します。
jdb -attach 'debug' or jdb -attach 8888
jdb の初期化と Test への接続が完了したら、ブレークポイントを設定して実行します。
stop in Test.main run
jdb ユーティリティーがブレークポイントに達します。
Java のデバッグとともにネイティブレベルのデバッグを実行するには、JDWP で実行中の Java プロセスにネイティブデバッガを使って接続します。
Windows では次の手順を実行します。
Visual Studio を開きます。
「ビルド」 -> 「デバッグ開始」 -> 「プロセスにアタッチ」を選択します。JDWP で実行中の Java プロセスを選択します。
「プロジェクト」 -> 「設定」 -> 「追加の DLL」を選択します。デバッグするネイティブ dll (Test.dll など) を追加します。
Test.dll のソースファイル (1 つ以上) を開き、ブレークポイントを設定します。
jdb ウィンドウで cont と入力します。プロセスが Visual Studio のブレークポイントに達します。
ネイティブレベルのデバッグに、Solaris OS では dbx ユーティリティーを使用でき、Linux では gdb ユーティリティーを使用できます。
JDWP を使ってアプレットをデバッグするには、次の手順を実行します。
Java コントロールパネルを起動します。
アプレットランタイムの設定を行います。
フィールド「Java ランタイムパラメータ」で次を入力します。
Windows の場合:
Djavaplugin.trace=true -Xdebug -Xrunjdwp: transport=dt_shmem,address=debug,server=y,suspend=y
Solaris OS および Linux の場合:
Djavaplugin.trace=true -Xdebug -Xrunjdwp: transport=dt_shmem,address=debug,server=y,suspend=y
ブラウザを起動してアプレットをロードすると、Java Plug-in がデバッグモードで起動され、アドレス debug (Windows) または 8888 (Solaris OS または Linux) でデバッガからの接続を待ちます。
コマンドウィンドウから jdb を実行し、アドレス debug (または 8888) に接続します。
jdb -attach debug Initializing jdb ... VM Started: No frames on the current call stack main[1]
jdb の初期化が完了したら、ブレークポイントを設定してから実行します。
sStop in MyApplet.func1 run
アプレットは、設定したブレークポイントに達するまでブラウザ内で実行されます。その後、アプレットのデバッグ、制御フローの確認、変数の監視などを行えます。