スレッドの誤った使用は、さまざまな種類の問題を引き起こす可能性があります。アクティブなスレッドが多すぎるとスレッドスタベーションが発生したり、スレッド同士がブロックし合い、アプリケーションの生存性に影響を与えたり、ロックの取得順序が間違っているとデッドロックにつながることもあります。さらに、スレッドに関する情報はデバッグの目的でも重要です。
JProfilerでは、スレッドプロファイリングは2つのビューセクションに分かれています。「Threads」セクションはスレッドのライフサイクルやスレッドダンプの取得を扱います。「Monitors & locks」セクションは、複数スレッドの相互作用を分析するための機能を提供します。
スレッドの調査
スレッド履歴ビューでは、各スレッドがタイムライン上の色付きの行として表示され、色は記録されたスレッド状態を示します。スレッドは作成時刻、名前、またはスレッドグループでソートでき、名前でフィルタリングすることも可能です。また、ドラッグ&ドロップでスレッドの順序を自由に並べ替えることもできます。monitorイベントが記録されている場合、「Waiting」や「Blocked」状態だった部分にマウスオーバーすると、関連するスタックトレースが表示され、monitor履歴ビューへのリンクも確認できます。
すべてのスレッドの表形式ビューは、スレッドmonitorビューで利用できます。スレッド作成時にCPU記録が有効になっている場合、JProfilerは作成元スレッドの名前を保存し、テーブルに表示します。下部には作成元スレッドのスタックトレースが表示されます。パフォーマンス上の理由から、JVMから実際のスタックトレースは取得せず、CPU記録の現在の情報を使用します。つまり、スタックトレースには呼び出しツリー収集のフィルタ設定を満たすクラスのみが表示されます。
プロファイリング設定で推定CPU時間の記録を有効にすると、テーブルにCPU Time列が追加されます。CPU時間はCPUデータを記録している場合のみ計測されます。
多くのデバッガと同様に、JProfilerでもスレッドダンプを取得できます。スレッドダンプのスタックトレースはJVMが提供する完全なスタックトレースであり、CPU記録には依存しません。異なるスレッドダンプは、2つ選択してShow Differenceボタンをクリックするとdiffビューアで比較できます。また、1つのスレッドダンプ内の2つのスレッドを選択し、コンテキストメニューからShow Differenceを選ぶことで比較することも可能です。
同じスタックトレースを持つスレッドダンプはグループ化されます。プラットフォームスレッドダンプ内のそのようなノードには、類似スレッドをすべて表示するコンテキストメニューアクションが利用できます。
Java 21以降をプロファイルしている場合、スレッドダンプビューには「Take thread dump with virtual threads」アクションが用意されています。プラットフォームスレッドも仮想スレッドダンプに含まれます。
スレッドダンプは、「Trigger thread dump」トリガーアクションやAPI経由でも取得できます。
ロック状況の分析
すべてのJavaオブジェクトには、2つの同期操作に使用できるmonitorが関連付けられています。スレッドはmonitor上で待機し、他のスレッドが通知を発行するのを待つことができ、またはmonitorのロックを取得して、他のスレッドがロックの所有権を手放すまでブロックされることもあります。さらに、java.util.concurrent.locksパッケージには、より高度なロック戦略を実装するためのクラスが用意されています。このパッケージのロックはオブジェクトのmonitorを使用せず、別のネイティブ実装となっています。
JProfilerは、上記両方のメカニズムに対するロック状況を記録できます。ロック状況には、1つまたは複数のスレッド、monitorまたはjava.util.concurrent.locks.Lockのインスタンス、そして一定時間を要する待機またはブロック操作が含まれます。これらのロック状況は、monitor履歴ビューでは表形式で、ロック履歴グラフでは視覚的に表示されます。
ロック履歴グラフは、個々のmonitorイベントの継続時間よりも、関与するすべてのmonitorとスレッドの関係全体に注目します。ロック状況に関与するスレッドとmonitorは青とグレーの長方形で描画され、デッドロックの場合は赤で表示されます。黒い矢印はmonitorの所有権を示し、黄色い矢印は待機中のスレッドから関連monitorへの関係を示します。点線の赤い矢印は、スレッドがmonitorの取得を試みて現在ブロックされていることを示します。CPUデータが記録されていれば、ブロックや待機矢印にマウスオーバーすることでスタックトレースが表示されます。これらのツールチップには、monitor履歴ビューの該当行へのハイパーリンクも含まれます。
表形式のmonitor履歴ビューではmonitorイベントが表示されます。イベントには継続時間があり、列として表示されるため、テーブルをソートして重要なイベントを見つけることができます。表形式ビューで任意の行を選択すると、Show in Graphアクションでグラフにジャンプできます。
各monitorイベントには関連するmonitorがあります。Monitor Class列には、monitorとして使用されているインスタンスのクラス名、またはJavaオブジェクトが関連付けられていない場合は「[raw monitor]」と表示されます。いずれの場合も、monitorには一意のIDがあり、別の列に表示されるため、同じmonitorの利用を複数イベントにわたって関連付けることができます。各monitorイベントには、操作を実行している待機スレッドと、オプションで操作をブロックしている所有スレッドがあります。利用可能な場合は、それらのスタックトレースがビュー下部に表示されます。
monitorインスタンスについてさらに調査したい場合は、monitor履歴ビューおよびロック履歴グラフの両方で利用できるShow in Heap Walkerアクションを使うことで、heap walkerへのリンクが表示され、monitorインスタンスが新しいオブジェクトセットとして選択されます。
注目するイベントの絞り込み
monitorイベントの分析における根本的な問題の1つは、アプリケーションが非常に高頻度でmonitorイベントを生成する場合があることです。そのため、JProfilerでは待機およびブロックイベントに対してデフォルトのしきい値が設定されており、これ未満のイベントは即座に破棄されます。これらのしきい値はビュー設定で定義されており、より長いイベントに注目したい場合は増やすことができます。
記録されたイベントには、さらにフィルタを適用できます。monitor履歴ビューでは、しきい値、イベントタイプ、テキストフィルタがビュー上部に用意されています。ロック履歴グラフでは、注目するスレッドまたはmonitorを選択し、それらが関与するロック状況のみを表示できます。注目イベントはタイムライン上で異なる色で表示され、セカンダリナビゲーションバーでそれらのイベントを順番に移動できます。現在のイベントが注目イベントでない場合、現在のイベントと次の注目イベントの間にいくつイベントがあるかを両方向で確認できます。
選択したスレッドやmonitorがグラフから除外された場合も、そのロック状況が表示されます。これは、各monitorイベントが2つのロック状況、すなわち操作開始時と終了時で定義されるためです。また、完全に空のグラフも有効なロック状況であり、JVM内にロックが残っていないことを示します。
注目すべきイベント数を減らすもう1つの戦略は、ロック状況を累積することです。ロック履歴グラフの下部にはタイムラインがあり、すべての記録イベントが表示されます。ここでクリック&ドラッグして時間範囲を選択すると、その範囲に含まれるすべてのイベントのデータが上部のロックグラフに表示されます。累積グラフでは、各矢印が同じタイプの複数イベントを含む場合があります。その場合、ツールチップウィンドウにはイベント数と合計時間が表示されます。ツールチップ内のドロップダウンリストでタイムスタンプを選択し、異なるイベントを切り替えることもできます。
デッドロック検出
「Current locking graph」と「Current monitors」ビューは、JProfiler UIのアクションでトリガーされる「monitorダンプ」に基づいて動作します。monitorダンプを取得することで、進行中のイベントを調査できます。これには、履歴ビューでは表示できない、終了しないイベントであるデッドロックも含まれます。
ブロック操作は通常短時間ですが、デッドロックが発生した場合、両ビューで問題が恒久的に表示されます。さらに、現在のロックグラフでは、デッドロックを引き起こしているスレッドとmonitorが赤で表示されるため、すぐに問題を特定できます。
新しいmonitorダンプを取得すると、両ビューのデータが置き換えられます。「Trigger monitor dump」トリガーアクションやAPI経由でもmonitorダンプをトリガーできます。
monitor使用状況の統計
ブロックや待機操作をより高い視点から調査するために、monitor統計ビューではmonitor記録データからレポートを生成します。monitorイベントをmonitor、スレッド名、またはmonitorのクラスごとにグループ化し、各行の累積回数や継続時間を分析できます。























