スレッドを不適切に使用すると、さまざまな問題が発生する可能性があります。アクティブなスレッドが多すぎるとスレッドの枯渇につながり、スレッド同士がブロックし合ってアプリケーションの生存性に影響を与えたり、不適切な順序でロックを取得してデッドロックを引き起こしたりすることがあります。さらに、デバッグ目的においてもスレッドに関する情報は重要です。
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ビューアーで異なるスレッドダンプを比較できます。また、単一のスレッドダンプから2つのスレッドを選択し、コンテキストメニューからShow Differenceを選択して比較することも可能です。
同じスタックトレースを持つスレッドダンプはグループ化されます。プラットフォームスレッドダンプ内のこのようなノードには、類似するすべてのスレッドを表示するためのコンテキストメニューアクションが用意されています。
Java 21以降をプロファイルする場合、スレッドダンプビューで個別の「Take Thread Dump With Virtual Threads」アクションを利用できます。仮想スレッドダンプにはプラットフォームスレッドも含まれます。
スレッドダンプは、「Trigger thread dump」トリガーアクションまたはAPI経由でも取得できます。
ロック状況の分析
すべてのJavaオブジェクトには関連付けられたmonitorがあり、2つの同期操作に使用できます。スレッドは別のスレッドがそのmonitorに対して通知を発行するまで待機(wait)するか、monitorのロックを取得できます(別のスレッドがロックの所有権を解放するまでブロックされる可能性があります)。さらにJavaでは、より高度なロッキング戦略を実装するために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オブジェクトがmonitorに関連付けられていない場合は「[raw monitor]」と表示されます。いずれの場合も、monitorには独立したカラムに表示される一意のIDがあるため、複数のイベントにわたって同一のmonitorの使用状況を関連付けることができます。各monitorイベントには操作を実行している待機スレッドがあり、オプションで操作をブロックしている所有スレッドが存在します。利用可能な場合、それらのスタックトレースはビューの下部に表示されます。
monitorインスタンスについてさらに詳しく調べたい場合、monitor履歴ビューとロック履歴グラフの両方にあるShow Selection In Heap Walkerアクションを使用すると、ヒープウォーカーへのリンクが提供され、そのmonitorインスタンスが新しいオブジェクトセットとして選択されます。
関心のあるイベントの絞り込み
monitorイベントの分析における根本的な問題の1つは、アプリケーションが非常に高い頻度でmonitorイベントを生成する可能性があることです。そのため、JProfilerには待機およびブロックイベントに対するデフォルトのしきい値が設定されており、それを下回るイベントは即座に破棄されます。これらのしきい値はビュー設定で定義されており、より長時間のイベントに焦点を当てるために値を大きくすることができます。
記録されたイベントに対して、さらにフィルターを適用することもできます。monitor履歴ビューの上部には、しきい値、イベントタイプ、およびテキストフィルターが用意されています。ロック履歴グラフでは、関心のあるスレッドまたはmonitorを選択し、マークされたエンティティが関与するロック状況のみを表示できます。関心のあるイベントはタイムライン上で異なる色で表示され、それらのイベント間を移動するためのセカンダリナビゲーションバーが用意されています。現在のイベントが関心のあるイベントでない場合、現在のイベントと次の関心のあるイベントとの間に前後どちらの方向にいくつのイベントがあるかを確認できます。
選択したスレッドまたはmonitorが存在するロック状況に加えて、それらがグラフから削除されるロック状況も表示されます。これは、各monitorイベントが操作の開始時と終了時という2つのロック状況によって定義されるためです。これはまた、完全に空のグラフも有効なロック状況であり、JVM内にロックがもう存在しないことを示していることを意味します。
注意を払うべきイベントの数を減らすためのもう1つの戦略は、ロック状況の累積です。ロック履歴グラフの下部には、記録されたすべてのイベントを表示するタイムラインがあります。その中でクリックしてドラッグすると時間の範囲が選択され、含まれるすべてのイベントのデータが上のロックグラフに表示されます。累積グラフでは、各矢印に同じタイプの複数のイベントが含まれる場合があります。その場合、ツールチップウィンドウにはイベント数と含まれる全イベントの合計時間が表示されます。ツールチップウィンドウのドロップダウンリストにはタイムスタンプが表示され、異なるイベント間を切り替えることができます。
デッドロックの検出
「Current locking graph」ビューおよび「Current monitors」ビューは、JProfiler UIのアクションでトリガーされる「monitor dump」に対して動作します。monitor dumpを使用すると、現在進行中のイベントを検査できます。これには、決して終了せず履歴ビューには表示できないイベントであるデッドロックが含まれます。
通常、ブロック操作は短時間で終わりますが、デッドロックが発生した場合は、両方のビューに問題が恒久的に表示されます。さらに、現在のロックグラフではデッドロックを引き起こしているスレッドとmonitorが赤色で表示されるため、このような問題を即座に特定できます。
新しくmonitor dumpを取得すると、両方のビューのデータが置き換えられます。monitor dumpは、「Trigger monitor dump」トリガーアクションまたはAPI経由でトリガーすることもできます。
monitor使用統計
ブロックおよび待機操作をより俯瞰的な視点から調査するために、monitor統計ビューではmonitor記録データからレポートを算出します。monitorイベントをmonitor、スレッド名、またはmonitorのクラスごとにグループ化し、各行の累積カウントと所要時間を分析できます。























