NetBeans Profiler 5.5 チュートリアル
この記事は NetBeans Profiler 5.5 を対象にしています。 NetBeans Profiler 5.0 または Profiler Milestone 8 を使用している場合は、こちらのバージョンを使用してください。
予想される所要時間: 70 分
NetBeans Profiler は、アプリケーションの実行時動作に関する重要な情報を提供する強力なツールです。 スレッドの状態、CPU パフォーマンス、およびメモリーの使用状況を監視でき、プロファイルによるオーバーヘッドも比較的小さく抑えます。 このチュートリアルでは、NetBeans Profiler を使用して次のタスクを実行する方法を示します。
- アプリケーションの次の実行時動作を監視する
- ヒープメモリーサイズ
- ガベージコレクションの統計
- スレッド数
- スレッドの状態: 実行中、休眠中、待機中、ブロック
- アプリケーションのメソッドに使用されている CPU 時間を特定する
- アプリケーションによるオブジェクトの作成を監視する
- Java SE および Java EE アプリケーションをプロファイルする
前提条件
このチュートリアルは、基礎的な Java プログラミング経験のある読者を対象にしています。
このチュートリアルに必要なソフトウェア
このドキュメントで使用している表記法
- <NETBEANS_HOME> - NetBeans IDE のインストールディレクトリ
- <USER_HOME> - ユーザーのホームディレクトリ
- <tutorial_root> - チュートリアル用の zip ファイルの展開先ディレクトリ
- このドキュメントでは、チュートリアル用の zip ファイルを展開したディレクトリを <tutorial_root> と表記します。 zip ファイルの名前は profilertutorial.zip です。
- チュートリアル用の zip ファイルを <tutorial_root> に展開すると、netbeansprofiler というサブディレクトリが作成されます。 たとえば、Windows の場合、zip ファイルをドライブ E のルート (E:\) に展開すると、E:\netbeansprofiler が作成されます。 Solaris または Linux の場合、zip ファイルを /home/<ユーザー名> ディレクトリに展開すると、/home/<ユーザー名>/netbeansprofiler ディレクトリが作成されます。
チュートリアルの課題
リソース
チュートリアル環境のインストールと設定
チュートリアルを開始する前に、次の手順を実行します。
- NetBeans IDE を起動し、IDE が動作していることを確認します。
- Windows では、NetBeans IDE アイコンをダブルクリックします。
- Solaris または Linux では、端末ウィンドウを開き、<NETBEANS_HOME>/bin/netbeans と入力します。
-
「プロファイル」>「ヘルプ」>「Profiler について...」を選択して、NetBeans Profiler がインストールされていることを確認します。
Swing アプリケーションのスレッド状態の監視 (15 分)
この課題では、NetBeans Profiler を使用して、Java SE アプリケーション内のスレッドの状態を監視する方法を学びます。 これにより、サンプルの Swing アプリケーションでパフォーマンスの問題を診断できます。
背景情報
Swing ライブラリには、Java SE アプリケーション用のグラフィカルユーザーインタフェースコンポーネントがあります。 Swing ライブラリでは複数のスレッドが使用されます。NetBeans Profiler は、各スレッドで発生する処理の量を把握できる強力なツールです。 各スレッドの処理量を把握することにより、パフォーマンスの問題を解決できます。
実行手順
- 「ファイル」>「プロジェクトを開く」を選択します。 <tutorial_root>/netbeansprofiler/exercises フォルダに移動します。 「exercise1」フォルダを選択し、「プロジェクトフォルダを開く」ボタンをクリックします。
- 「プロジェクト」ウィンドウで、「exercise1」エントリを右クリックし、「プロジェクトの生成物を削除して構築」を選択します。 もう一度「exercise1」エントリを右クリックし、「プロジェクトを実行」を選択します。 次に示すようなウィンドウが表示されます。

- 「Seconds Before Notification」は 30 に設定されています。
- 「Start!」ボタンをクリックします。 再描画が正しく行われません。
- 「Exit」ボタンをクリックします。 アプリケーションがまったく応答しません。
- その他の問題を確認するため、このウィンドウの上に別のウィンドウを重ねて、このウィンドウの一部が隠れるようにします。 上のウィンドウを移動したときに、サンプルアプリケーションのウィンドウが正しく再描画されません。 次に例を示します。

- 30 秒が経過すると、次に示すようなメッセージボックスが表示されます。 メッセージボックスの「了解」ボタンをクリックします。

- アプリケーションのウィンドウが再度応答するようになります。 「Exit」ボタンをクリックしてアプリケーションを終了します。
- 「プロファイル」>「主プロジェクトをプロファイル」を選択します。
- プロジェクトの構築スクリプトを変更する許可を求めるダイアログが表示されたら、「了解」をクリックします。 次に例を示します。

- 「プロファイルタスクの選択」ダイアログが表示されます。 大きな「アプリケーションを監視」ボタンをクリックします。
- 「スレッド監視を有効」チェックボックスが選択されている必要があります。
- 「実行」ボタンをクリックします。
- Profiler の調整情報を最初に収集する必要があることを伝えるダイアログが表示された場合は、そのダイアログの「了解」ボタンをクリックします。 次に例を示します。

調整が完了すると、ダイアログが表示されます。そのダイアログの「了解」ボタンをクリックします。 次に例を示します。

プロファイルを開始するには、手順 9 に戻ります。
- アプリケーションが起動し、次に示すような Profiler コントロールパネルが表示されます。

- Profiler のメインウィンドウに、スレッドの状態が表示されます。次に例を示します。

スレッドの状態の表示には、次の色分けが使用されます。
- 緑: スレッドは実行中であるか、実行する準備が整っています。
- 紫: スレッドは Thread.sleep() で休眠中です。
- 黄: スレッドは Object.wait() の呼び出しで待機中です。
- 赤: スレッドは同期化したブロックまたはメソッドに入ろうとしてブロックされました。
- サンプルの Swing アプリケーションのウィンドウを探します。NetBeans IDE のウィンドウの下に隠れている可能性があります。 サンプルアプリケーションの「Start!」ボタンをクリックし、AWT-EventQueue-0 というラベルのスレッドに注目します。 次の例に示すように、このスレッドは緑になり、30 秒間その状態を保ちます。
このグラフから、アプリケーションが応答していない理由がわかります。 AWT-EventQueue-0 というスレッドは、ウィンドウイベントを処理するために Swing で使用されるイベントディスパッチスレッド (EDT) です。 正常な Swing アプリケーションでは、EDT は多くの時間、待機状態にあり、実行される時間はほとんどありません。イベントのディスパッチに必要な短い時間に限り実行されます。 ただし、アプリケーション内のイベントハンドラが短時間で戻らないと、プログラムはこの例のように応答しなくなります。
- 30 秒が経過すると、アプリケーションのメッセージボックスが表示されます。 メッセージボックスを探し (NetBeans IDE ウィンドウの下に隠れている可能性があります)、「了解」ボタンをクリックします。 次に、サンプルアプリケーションの「Exit」ボタンをクリックしてアプリケーションを終了します。
- 「プロジェクト」ウィンドウは Profiler コントロールパネルと領域を共有しています。「プロジェクト」ウィンドウを表示するには、「プロジェクト」タブをクリックします。
- 「プロジェクト」ウィンドウの「exercise1」エントリをダブルクリックして展開し、「ソースパッケージ」および「profilingthreads」エントリを展開します。 「DisplayForm.java」エントリを右クリックし、「開く」を選択します。
- DisplayForm.java が表示されているエディタウィンドウで、132 行目から 157 行目までのコードブロックのコメントを解除します。 ヒント: 行番号を表示するようにエディタを設定していない場合は、「表示」>「行番号を表示」を選択します。
- DisplayForm.java が表示されているエディタウィンドウで、122 行目から 128 行目までのコードブロックを削除またはコメントにします。 次の図で強調表示されている箇所です。

- 「ファイル」>「保存」を選択します。 これで、EDT を不適切に使用していたコードが削除され、より強力な方法に置き換わりました。 アプリケーションは前よりも応答が良くなっているはずです。
- 「構築」>「主プロジェクトを構築」を選択するか、F11 キーを押します。
- 「プロファイル」>「主プロジェクトをプロファイル」を選択します。
- 「プロファイルタスクの選択」ダイアログが表示されます。 大きな「アプリケーションを監視」ボタンをクリックします。
- 「スレッド監視を有効」が選択されていることを確認します。
- 「実行」ボタンをクリックします。
- サンプルプログラムが表示されたら、「Start!」ボタンをクリックします。 Profiler のスレッドグラフの内容が前とは異なることがわかります。次に例を示します。
EDT は黄で、アプリケーションによって作成された「Our SwingWorker #1」というスレッドは緑です。 EDT は時間のかかるタスクには使用されておらず、その結果、ボタンやその他のプログラムコントロールの応答が良くなっています。
- サンプルプログラムの「Exit」ボタンをクリックします。
- Profiler のグラフで「AWT-EventQueue-0」スレッドを右クリックし、「スレッドの詳細」を選択します。 状態ごとの時間を示す円グラフが表示されます。次に例を示します。
このグラフから、プログラムの各スレッドで使われている時間が適正かどうかを判断できます。 この例は、コードを修正したあとの結果なので、EDT がほとんどの時間、待機状態にあることがわかります。これは、EDT の本来の動作です。
- 「プロジェクト」ウィンドウで、「exercise1」エントリを右クリックし、「プロジェクトを閉じる」を選択します。
まとめ
この課題では、Profiler を使用してアプリケーションを起動する方法と、Profiler のスレッド情報グラフを解釈して Swing アプリケーションのパフォーマンスの問題を特定する方法を学びました。
ページの先頭へ
メソッドに使用されている CPU 時間の確認 (15 分)
この課題では、Profiler を使用して、アプリケーションの特定のメソッドに要する時間を確認します。
背景情報
CPU のパフォーマンスの問題は、一般に、アプリケーション内の特定の機能に関連しています。 たとえば、レポートシステムで、あるレポートの実行が、ほかのレポートの実行より遅い場合があります。 アプリケーションでパフォーマンスの問題が発生している部分だけをプロファイルすることで、プロファイラによるオーバーヘッドを大幅に軽減できます。 この課題では、NetBeans Profiler を使用して、Web アプリケーションでの CPU 使用状況を確認します。 ここで使用する例の Web アプリケーションは、課題 3 でも使用します。課題 3 では、Profiler を使用してメモリーリークを検出する方法を示します。
実行手順
- 「ファイル」>「プロジェクトを開く」を選択します。 <tutorial_root>/netbeansprofiler/exercises フォルダに移動します。 「exercise2」フォルダを選択し、「主プロジェクトとして開く」が選択されていることを確認します。 「プロジェクトフォルダを開く」ボタンをクリックします。
- メニューから、「構築」>「主プロジェクトの生成物を削除して構築」を選択します。
- またメニューから、「プロファイル」>「主プロジェクトをプロファイル」を選択します。 プロジェクトの構築スクリプトを変更する許可を求めるダイアログが表示されたら、「了解」をクリックします。
- 「プロファイルタスクの選択」ダイアログの「パフォーマンスを解析」ボタンをクリックします。
- 「アプリケーションの一部」ラジオボタンを選択します。 次に、「アプリケーションの一部」ラジオボタンの横にある「選択」ボタンをクリックします。 「Root メソッドの指定」ウィンドウが表示されます。
- 「Root メソッドの指定」ウィンドウで、「プロジェクトから追加...」ボタンをクリックして、プロファイルする root メソッドを追加します。 「メソッドの選択」ウィンドウが表示されます。
- 「クラス名」テキストフィールドに demo.Performance と入力し、Enter キーを押します。
- root メソッドのリストで「processRequest」メソッドをクリックして選択し、「了解」ボタンをクリックします。 これで、パフォーマンス解析の root メソッドとして、demo.Performance.processRequest が選択されました。 これにより、demo.Performance.processRequest メソッド、このメソッドが呼び出すすべてのメソッド、これらのメソッドが呼び出すすべてのメソッドがプロファイルされます。 Profiler では、demo.Performance.processRequest から順にメソッド呼び出しグラフを解析して、プロファイルの必要なメソッドが判別されます。 必要なメソッドだけがプロファイルされるので、アプリケーションの残りの部分は、プロファイルによるオーバーヘッドの影響を受けずに、最高速度で動作できます。
- 「Root メソッドの指定」ウィンドウの「了解」ボタンをクリックします。
- 「パフォーマンスを解析」ウィンドウの「フィルタ」リストから「簡易フィルタ」を選択し、このエントリの横にある「...」ボタンをクリックして、プロファイルしないメソッドを指定します。 「簡易フィルタの設定」ウィンドウが表示されます。 「除く」ラジオボタンが選択されていることを確認します。 「フィルタ値」テキストフィールドに org.apache と入力し、「了解」ボタンをクリックします。 これで、org.apache パッケージとその子パッケージのすべてのメソッドは、選択した root メソッドから呼び出されても、プロファイルされません。 これにより、プロファイルによるオーバーヘッドが軽減され、関係のない情報が除外されます。
- 「プロファイルタスクの選択」ウィンドウで、「実行」ボタンをクリックします。 調整情報の入力を求めるダイアログが表示されたら、そのダイアログの「了解」ボタンをクリックします。調整が完了したことを示すダイアログが表示されたら、そのダイアログの「了解」ボタンをクリックします。
- IDE にバンドルされている Tomcat サーバーが起動し、Web ブラウザのウィンドウに Web アプリケーションの index.jsp ページが表示されます。 同時に、Profiler がバックグラウンドで実行されます。 注: index.jsp ページは、デフォルトで、フォーカスのあるブラウザウィンドウに表示されます。別のブラウザウィンドウを開いておくと、Web アプリケーションの実行中にこの説明を見ることができます。
- root メソッドとして demo.Performance.processRequest を選択したので、Web アプリケーション内でその root メソッドを実行する部分を使用する必要があります。 Web ブラウザで「Performance Problems」をクリックして「Performance」デモページを表示します。 「Performance」デモページで、テキストフィールドに 123456 と入力します。 optimized オプションは選択しないでください。 「Submit Query」ボタンをクリックすると、123456 以下の最大素数が計算されます。
- 最大素数の計算に使用されるアルゴリズムには、パフォーマンスの問題があるので、応答が表示されるまでに数秒かかります。 また、Profiler によって processRequest メソッドのパフォーマンスが監視されるときにオーバーヘッドが生じます。 計算結果の 123449 がブラウザに表示されたら、
ボタンをクリックするか、「プロファイル」>「収集結果のスナップショットを作成」を選択します。 CPU 使用状況のスナップショットの下部にある「結合」タブをクリックします。 次に示すような最新のパフォーマンス結果が Profiler で表示されます。
上のウィンドウには、root メソッドから始まる完全なメソッド呼び出しグラフが表示されます。 下のウィンドウには、アプリケーションのホットスポット、つまり実行に時間がかかったメソッドが一覧表示されます。
- 結果を確認して解釈すると、processRequest メソッドが合計で 26929 ミリ秒間実行されたことがわかります。 ただし、processRequest メソッド自体の命令の実行にはほとんど時間がかかっていません。processRequest の「セルフタイム」は 207 ミリ秒です。 大部分の時間は、processRequest から呼び出されたメソッドに使われています。 下のウィンドウに表示されるホットスポットは、「セルフタイム」別にソートされています。 このリストを見ると、calculate メソッドが実行時間の 99 % を占めていることがわかります。 このことは、calculate に割り当てられている処理の量を考えれば、驚くべきことではありません。
- アプリケーションを最適化する方法を決定できるように、NetBeans Profiler では、コード内の予想外の障害や、アプリケーションの拡張を妨害する障害を特定できます。 ホットスポットリストの「calculate」エントリをクリックして、時間がかかった処理を詳しく調べます。これにより、呼び出しグラフウィンドウが更新され、calculate が表示されます。 calculate メソッドはほかのメソッドを呼び出さないので、「calculate」エントリを右クリックし、「ソースへ」を選択して、ソースコードを調べます。 すると、非常に効率の悪いアルゴリズムが使用されているので、再設計が必要であることがわかります。
- 「プロファイル」>「収集結果をリセット」を選択して、Profiler のバッファーを消去します。 calculate の実行時と、最適化されたアルゴリズムである calculate2 を比較するため、Web ブラウザで最適化オプションを選択してから、「Submit Query」をクリックします。 結果が収集されるのを待ち、もう一度「プロファイル」>「収集結果のスナップショットを作成」を選択します。 processRequest メソッドの実行時間は 39.3 ミリ秒で、calculate2 メソッドの実行には 33.2 ミリ秒しかかからなかったことがわかります。

- 注: 次の課題は、この課題の続きですので、現在表示しているウィンドウは閉じないでください。
まとめ
この課題では、Profiler を使用して、単一のメソッドと、そのメソッドから呼び出されるすべてのメソッドのパフォーマンス解析を行う方法を学びました。
ページの先頭へ
オブジェクト作成のプロファイルによるメモリーリークの検出 (20 分)
課題 2 の続きとして、この課題では、プロファイルの種類を切り替える方法を学びます。また、さらに重要なポイントとして、アプリケーションによるオブジェクトの作成を監視するために、プロファイラのグラフを解釈する方法を学びます。 メモリーリークの例も紹介します。
実行手順
- この課題は課題 2 の続きですので、必ず課題 2 の手順を実行してください。
- メニューから、「プロファイル」>「プロファイルを変更」を選択します。
- 「プロファイルタスクの選択」ダイアログで、大きな「アプリケーションを監視」ボタンをクリックします。
- 「実行」ボタンをクリックします。 IDE の左側に Profiler コントロールパネルが表示されます。
ボタンをクリックするか、「プロファイル」>「表示」>「遠隔測定の概要」を選択します。 次に示すように、NetBeans Profiler の下部の出力ウィンドウに 3 つのグラフが表示されます。図をクリックすると、拡大表示されます。
左側のグラフで、赤の部分は、JVM ヒープの割り当てサイズを示しています。 紫の部分は、実際に使用されているヒープ領域を示しています。 上記の例では、最後の更新時に割り当てられていたヒープサイズは 10M バイトを超えていました。 そのうち、Java オブジェクトを格納するために実際に使用されていたのは 4M バイトをわずかに超えた量です。
右側のグラフは、JVM 内でアクティブなスレッドの数を示しています。
中央のグラフは、2 つの重要なヒープ統計を示しています。
- 青い線 (このグラフでは軸と重なっている) は、実行時間のうち、JVM によるガベージコレクションが占める割合を示し、グラフの右側の Y 軸がその目盛りです。 JVM によるガベージコレクションに要する時間は、アプリケーションの実行に使用できない時間です。 したがって、青い線が高い割合を示している場合は、ヒープサイズを大きくして JVM を調整するか (-Xmx パラメータに関するドキュメントを参照)、別のガベージコレクションアルゴリズムに切り替えることを検討する必要があります。
-
赤い線は、生存中世代を示し、グラフの左側の Y 軸がその目盛りです。 生存中世代数は、JVM のヒープ上にあるすべての Java オブジェクトの異なる年齢の数です。ここでいう「年齢」とは、オブジェクトが生存してきたガベージコレクションの回数として定義されます。 生存中世代の値が低い場合は、ヒープ上にあるほとんどのオブジェクトがほぼ同じ時間生存していることを示しています。 ただし、生存中世代の値が急増している場合は、アプリケーションで、すでに割り当てられている多数の古いオブジェクトへの参照を維持しながら、新しいオブジェクトも割り当てていることを示しています。 これらの古いオブジェクトをアプリケーションで実際に使用していない場合は、メモリーを浪費、つまり「リーク」していることになります。
- Profiler では、CPU パフォーマンスまたはメモリー使用状況の詳細な解析 (計測) を行うことができますが、この両方を同時に行うことはできません。 JVM のヒープ上にあるオブジェクトの割り当てとガベージコレクションに関する詳細な情報を調べるには、Profiler の設定を変更します。
ボタンをクリックするか、「プロファイル」>「プロファイルを変更」を選択します。
- 「メモリー使用を解析」ボタンをクリックします。
- 「オブジェクト作成とガベージコレクションの両方を記録」ラジオボタンを選択します。
- 「割り当てのスタックトレースを記録」チェックボックスを選択します。
- 「了解」ボタンをクリックします。
- メモリーの使用状況を解析することにしたので、メモリーが効率的に使用されているかどうかを判断するために、アプリケーションを使用する必要があります。 アプリケーションの index.jsp ページが再表示されるまで、ブラウザの「戻る」ボタンをクリックします。 次に、「Memory Leak」ボタンをクリックして、「MemoryLeak」デモページに移動します。
- 「MemoryLeak」デモページで「Start Leaking」をクリックします。
- 次の例に示すように、生存中世代のグラフの線が急上昇します。 これはメモリーリークの可能性を示しています。
- 「プロファイル」>「表示」>「ライブ結果」を選択します。 JVM ヒープで割り当てられているオブジェクトの動的ビューが表示されます。 デフォルトでは、各クラスのすべてのインスタンスで使用されているバイト数に従ってソートされます。 メモリーリークの可能性があるので、「世代数」列をクリックして、各クラスのオブジェクトの世代数に従ってソートします。 ソート結果の例を次に示します。
各列で、オブジェクトの割り当てとメモリー使用状況に関する情報を確認できます。
- 右から 3 列目の「割り当てオブジェクト数」は、Profiler で監視されているオブジェクトの数を示しています。 この例では、float[] のインスタンスが 23 個監視されています。 この数値は、デフォルトでは、アプリケーションによって実際に割り当てられたオブジェクトの数の約 10 % になります。 Profiler では、作成されるオブジェクトのサブセットだけが監視されるので、JVM で生じるオーバーヘッドを大幅に軽減できます。これにより、アプリケーションは最高速度に近い速度で実行できます。
- 「ライブオブジェクト数」は、JVM のヒープ上にあり、メモリーを占有している、割り当てられたオブジェクトの数を示しています。
- 2 つの「ライブバイト数」列は、ライブオブジェクトによって使用されているヒープメモリーの量を示しています。 一方の列にはグラフ、もう一方の列にはテキストが表示されます。
- 「平均年齢」の値は、ライブオブジェクト数を使用して計算されます。 各オブジェクトの年齢は、オブジェクトが生存してきたガベージコレクションの回数です。 年齢の合計をライブオブジェクト数で割った値が平均年齢です。
- 「世代数」の値も、ライブオブジェクト数を使用して計算されます。 オブジェクトの年齢は、オブジェクトが生存してきたガベージコレクションの回数です。 「世代数」の値は、ライブオブジェクトの異なる年齢の数です。
- プログラムの実行を続けると、Profiler の表示は更新されます。 float[] と double[] のエントリに注目してください。 世代数の値が増加していることがわかります。 その結果、float[] と double[] はリスト内で上の方に移動し続けます。 最終的に、リストの上部に達し、同じく世代数が増加した java.util.HashMap$Entry の下に表示されます。 アプリケーションの実行を続けると、java.util.HashMap$Entry、float[]、および double[] の世代数は増加しますが、その他のクラスの世代数は増加しません。 次に例を示します。図をクリックすると、拡大表示されます。
- 世代数の値が増加を続ける原因を調べるには、「プロファイル」>「収集結果のスナップショットを作成」を選択します。 結果を「世代数」列でソートします。 「double[]」エントリを右クリックし、「割り当てスタックトレースを表示」を選択します。 1 つ以上の double[] オブジェクトを割り当てているすべてのメソッドが表示されます。 次に例を示します。図をクリックすると、拡大表示されます。
double[] オブジェクトを割り当てているメソッドのうち、世代数の値が高い double[] オブジェクトを作成したメソッドは 1 つだけです。 このメソッドは、demo.memoryleak.LeakThread クラスの run() です。
- run() メソッドのエントリを右クリックし、「ソースへ...」を選択します。 次に示すようなソースコードが表示されます。
double[] オブジェクトと float[] オブジェクトは、割り当てのあと、HashMap に配置しています。 しかし、これらのオブジェクトを削除していないので、HashMap で参照が保持され、オブジェクトは JVM のガベージコレクションの対象になりません。 これは、Java で一般的なメモリーリークの原因です。 オブジェクトを Map に配置したあと、忘れてしまうのです。 この例で使用している Map は HashMap なので、それに関連付けられている java.util.HashMap$Entry オブジェクトもリークしています。
- 任意: 「メモリー結果」タブに戻って、「java.util.HashMap$Entry」エントリを右クリックし、「割り当てスタックトレースを表示」を選択すると、さらに興味深いスタックトレースのリストを見ることができます。 スタックトレースリストのノードを展開し、demo.memoryleak.LeakThread クラスの run() メソッドからの呼び出しを簡単に特定できるかどうかを試してみてください。
- 「プロファイル」>「停止」を選択するか、
ボタンをクリックして、プロファイルセッションを終了します。
- 「プロジェクト」ウィンドウで、「exercise2」エントリを選択し、メニューから「ファイル」>「プロジェクトを閉じる」を選択します。
まとめ
この課題では、Profiler を使用して、アプリケーションによるオブジェクトの作成を監視する方法を学びました。 また、アプリケーションでメモリーリークが発生しているときに Profiler によって提供される情報を確認しました。
ページの先頭へ
Enterprise Java Bean モジュールのプロファイル (20 分)
この課題では、NetBeans Profiler で提供されている特定のサポートを使用して、Enterprise Java Bean (EJB) をプロファイルする方法を学びます。 また、プロファイラのフィルタを使用して、プロファイルによるオーバーヘッドと、報告される情報の量を制御する最適な方法も学びます。
背景情報
NetBeans Profiler には、EJB をプロファイルするためのサポートが用意されています。 このサポートにより、たとえば、プロファイルセッションを開始したあとで、プロファイル対象の EJB を呼び出す別のアプリケーションを簡単に実行できます。 EJB はアプリケーションサーバーで実行されるので、プロファイルによるオーバーヘッドを最小限に抑えるには特定の手法が必要です。 別のスレッドで EJB に対して行われた呼び出しを特定するためのツールも用意されています。
実行手順
- 「ファイル」>「新規プロジェクト」を選択します。
- 「カテゴリ」で、「サンプル」エントリを展開します。 「サンプル」の下にある「エンタープライズ」エントリをクリックします。
- 「プロジェクト」で、「InterceptorStateless」エントリをクリックし、「次へ」ボタンをクリックします。
- 「プロジェクトの場所」フィールドで、プロジェクトファイル用のフォルダを指定するか、デフォルトのフォルダを使用します。 「完了」ボタンをクリックします。
- サンプルプロジェクトのカタログから 3 つのプロジェクトが作成されます。 3 つのプロジェクトはすべて「プロジェクト」ウィンドウに表示されます。

InterceptorStateless-ejb は、.jar ファイルを生成する EJB モジュールプロジェクトです。 InterceptorStateless-app-client は、.jar ファイルを生成するエンタープライズアプリケーションクライアントプロジェクトです。 InterceptorStateless は、.ear ファイルを生成するエンタープライズアプリケーションです。
- 「InterceptorStateless」を右クリックし、コンテキストメニューから「プロジェクトを構築」を選択します。 InterceptorStateless はほかの 2 つのプロジェクトに依存しているので、これらのプロジェクトも構築されます。
- 「InterceptorStateless-ejb」を右クリックし、コンテキストメニューから「プロジェクトをプロファイル」を選択します。 使用する Java プラットフォームの指定を求めるダイアログが表示されたら、デフォルトのプラットフォームを選択します。 プロジェクトの構築スクリプトを変更する許可を求めるダイアログが表示されたら、「了解」をクリックします。
- 「プロファイルタスクの選択」ダイアログで、「パフォーマンスを解析」ボタンをクリックします。
- 「アプリケーション全体」オプションをクリックします。 「アプリケーションサーバーの起動をプロファイル」オプションが選択されていないことを確認します。
- 「フィルタ」リストから「簡易フィルタ」を選択し、このエントリの横にある「...」ボタンをクリックして、プロファイルするメソッド用のフィルタを指定します。 「簡易フィルタの設定」ウィンドウが表示されます。 「含む」ラジオボタンを選択します。 「フィルタ値」テキストフィールドに enterprise.interceptor_stateless_ejb と入力し、「了解」ボタンをクリックします。

enterprise.interceptor_stateless_ejb パッケージとその子パッケージのクラスに含まれるすべてのメソッドがプロファイルされます。その他のメソッドはプロファイルされません。 サイズの大きいアプリケーションや、EJB などの Java EE コンポーネントの場合、アプリケーション全体をプロファイルするときは、フィルタを指定することが重要です。 フィルタを指定しなかった場合、プロファイラによるオーバーヘッドの量が、パフォーマンスに大きく影響する可能性があります。
- 「実行」ボタンをクリックします。 バンドルされている Tomcat サーバーの停止を求めるダイアログが表示されたら、「了解」をクリックします。 アプリケーションサーバーをプロファイルモードで起動し、サンプルアプリケーションを配備して、プロファイルの準備を行うには、多少の時間がかかります。 処理が完了すると、次の例に示すように「構築成功」というメッセージが IDE の「出力」ウィンドウに表示されます。
- 「プロジェクト」ウィンドウで、「InterceptorStateless」エントリを右クリックし、コンテキストメニューから「プロジェクトを実行」を選択します。 IDE で InterceptorStateless-client-app が実際に実行されます。 このアプリケーションは、次に示すように、1 つの EJB に対してメソッドを呼び出し、その結果を報告する、単純なコマンド行ユーティリティーです。

- 「プロファイル」>「収集結果のスナップショットを作成」を選択します。 次に示すような CPU の結果ウィンドウが表示されます。
CPU の結果ウィンドウには、スレッドが一覧表示されます。表示されるスレッドの名前は、アプリケーションサーバーの実行ごとに変わる場合があります。
- EJB のメソッドは常に、アプリケーションサーバーのスレッドプールから選択されたスレッドで呼び出されます。 したがって、呼び出された最上位のメソッドを表示するには、次に示すように、1 つ以上のスレッドを展開します。図をクリックすると、拡大表示されます。

このメソッドのリストは、よく理解していないアプリケーションをプロファイルするときに特に役に立ちます。 プロファイルの対象をアプリケーションの EJB の特定のパッケージに限定する「含む」フィルタを指定することにより、呼び出されている最上位のメソッドを簡単に確認できます。 この例では、NullChecker クラスの checkIfNull() メソッド、および ArgumentsChecker、NullChecker、および StatelessSessionBean の各クラスのコンストラクタが最上位のメソッドです。
- これらのコンストラクタに使用された相対的な時間は非常に小さいので、その詳細情報はそれほど重要ではありません。 ただし、checkIfNull() メソッドに使用された時間を調べることは役に立ちます。 checkIfNull() メソッド内で時間がどのように使われたかを調べるには、その下にあるエントリを展開します。次に例を示します。図をクリックすると、拡大表示されます。

enterprise.interceptor_stateless_ejb パッケージとサブパッケージのクラスのメソッドだけが含まれるようにフィルタを設定したため、この表示は完全ではありません。 具体的には、ほかのパッケージのメソッドに使われた時間は表示されていません。
- 呼び出されている最上位の (root) メソッドがわかったので、プロファイラの設定を変更して、プロファイルによるオーバーヘッドを抑えながらこれらのメソッドに関する詳細情報を収集します。 「ナビゲート」>「クラスへ移動」を選択するか、Alt-Shift-O キーを押します。 「クラスへ移動」ダイアログの「クラス名」フィールドに NullChecker と入力し、Enter キーを押します。
- エディタに NullChecker.java ファイルが表示されます。 checkIfNull() メソッドの先頭行である 33 行目の任意の場所にカーソルを置きます。

- 「ツール」>「プロファイル用 Root メソッドとして追加」を選択します。 「設定値構成を選択」ダイアログで、「プリセット: アプリケーションの一部」をクリックし、「了解」ボタンをクリックします。
- 「プロファイル」>「プロファイルを変更」を選択します。
- 「プロファイルタスクの変更」ダイアログが表示されます。 「パフォーマンスを解析」セクションで「アプリケーションの一部」オプションをクリックします。
- 「アプリケーションの一部」オプションの横にある「選択」ボタンをクリックします。 「Root メソッドの指定」ダイアログが開き、checkIfNull() メソッドだけが表示されます。
- 「フィルタ」リストから「すべてのクラスをプロファイル」を選択します。 「パフォーマンスを解析」セクションは、次の例のようになります。
これで、1 つの root メソッドだけをプロファイルするように設定を変更しました。 ただし、NetBeans Profiler では、root メソッドが解析され、その root メソッドから呼び出されるすべてのメソッドもプロファイルされます。 root メソッドの呼び出しグラフ全体がプロファイルされるように、解析は再帰的に行われます。 プロファイルの対象を興味のあるメソッドだけに限定したところで、今度は、enterprise.interceptor_stateless_ejb パッケージ内のメソッドに限定されないようにフィルタを変更します。
- 「プロファイルタスクの変更」ダイアログの下部にある「了解」ボタンをクリックします。
- 「プロジェクト」ウィンドウで、「InterceptorStateless」エントリを右クリックし、コンテキストメニューから「プロジェクトを実行」を選択します。
- 「プロファイル」>「収集結果のスナップショットを作成」を選択します。 新しい CPU の結果ウィンドウが表示されます。
- CPU の結果ウィンドウの下部にある「ホットスポット」タブをクリックします。 次の例に示すような結果が表示されます。図をクリックすると、拡大表示されます。
前に収集した CPU 結果を含むウィンドウのタブをクリックすると、各ウィンドウに表示されているホットスポットを比較できます。 前のスナップショットには、適用されたフィルタにより、enterprise.interceptor_stateless_ejb パッケージのメソッドだけが表示されます。 前に使用したフィルタは、プロファイルによる必要以上のオーバーヘッドを抑えるために必要でした。このフィルタを使用することにより、プロファイル対象の EJB で興味のある最上位メソッドを特定できました。 このメソッドを root メソッドとして設定し、フィルタを削除することで、enterprise.interceptor_stateless_ejb パッケージ以外のメソッドに使われている時間も含めて、どこに時間がかかっているかに関する詳細を確認できます。
- 新しい CPU の結果ウィンドウで、initUpperCase() メソッドのエントリをクリックし、ウィンドウの下部にある「結合」タブをクリックします。 次の例に示すような結果が表示されます。図をクリックすると、拡大表示されます。
root メソッドとして選択した checkIfNull() メソッドと、「ホットスポット」リストで選択した initUpperCase() メソッドとの関係がよくわかります。 「ホットスポット」リストを見ると、initUpperCase() メソッドが 2 回呼び出されたことがわかります。 呼び出しツリーを見ると、initUpperCase() メソッドは 1 回しか呼び出されていません。 このような不一致は、アプリケーションサーバーまたは Web サーバーで実行しているコードをプロファイルするときに頻繁に発生します。呼び出しツリーはスレッドごとに表示されます。 ホットスポットはメソッドごとに表示され、すべてのスレッドでの呼び出しが集約されます。 initUpperCase() メソッドのその他の呼び出しを検索するには、「呼び出しツリー」ウィンドウの「順方向に検索を繰り返します」ボタン
をクリックします。 「呼び出しツリー」ウィンドウで、別のスレッドを含めた、initUpperCase() メソッドのその他の呼び出しが強調表示されます。
- 「プロファイル」>「停止」を選択します。
まとめ
この課題では、Profiler を使用して、EJB メソッドのパフォーマンスを確認する方法を学びました。 また、root メソッドを特定し、その root メソッドから呼び出されるメソッドに関する詳細情報を収集する方法も学びました。
ページの先頭へ
お疲れさまでした。 これで NetBeans IDE 5.5 Profiler チュートリアルは終了です。
次の手順
プロファイルに関する質問がある場合は、 Profiler の FAQ を参照してください。
Profiler プロジェクトについては、Profiler プロジェクトのホームページ を参照してください。