2 診断ツール

Java Development Kit (JDK)には、各種オペレーティング・システム固有の診断ツールおよびトラブルシューティング・ツールが用意されています。また、JDKで提供されるAPIを使用して、カスタム診断ツールを開発することもできます。

この章の構成は、次のとおりです。

診断ツールの概要

この項で説明するコマンド行ユーティリティのほとんどは、JDKに含まれているか、オペレーティング・システムのネイティブなツールやユーティリティです。

JDKコマンド行ユーティリティを使用すると、Javaランタイム環境にデプロイされているアプリケーションの問題を診断し、監視できます。

一般に、診断ツールやオプションは、様々なメカニズムを使用して報告対象の情報を取得します。それらのメカニズムは仮想マシン(VM)実装、オペレーティング・システムおよびリリースに固有のものです。通常、ツールの一部のみが、特定の時点で特定の問題に適用可能です。「-XX」という接頭辞が付いたコマンド行オプションは、Java HotSpot VMに固有のものです。「Java HotSpot VMコマンド行オプション」を参照してください。

ノート:

-XXオプションはJava APIの一部ではなく、リリースごとに変わる可能性があります。

これらのツールおよびオプションは、トラブルシューティングの対象となっている問題のタイプに応じて、いくつかのカテゴリに分けられます。場合によっては、1つ以上のカテゴリに分けられるツールやオプションもあります。

ノート:

この項で説明するコマンド行ユーティリティのいくつかは、試験的なものです。jstackjinfo、およびjmapユーティリティが、試験的なユーティリティの例です。以前のjstackjinfoおよびjmapユーティリティのかわりに最新の診断ツールjcmdの使用をお薦めします。

JDK Mission Control

JDK Mission Control (JMC)は、本番時のプロファイリングおよび診断ツールです。これには、わずかなパフォーマンス・オーバーヘッドでJavaアプリケーションをモニターおよび管理するためのツールが含まれており、本番で実行されているアプリケーションの監視に適しています。

JMCは、通常のJDKインストールには含まれません。JMCのダウンロードとドキュメントの詳細は、JDK Mission Controlのページを参照してください。

JMCは次のもので構成されます:
  • JVMブラウザには、実行しているJavaアプリケーションとそのJVMが表示されます。
  • JMXコンソールは、JVMをモニターおよび管理するためのメカニズムです。実行中のJVMに接続し、その特性をリアル・タイムで収集して表示し、マネージドBean (MBean)を通じて一部のランタイム・プロパティを変更できます。特定のイベントでトリガーされるルールも作成できます(たとえば、アプリケーションのCPU使用率が90%に達した場合に電子メールを送信するなど)。

  • フライト・レコーダ(JFR)は、実行中のJavaアプリケーションに関する診断およびプロファイリングのデータを収集するツールです。JVMに統合されており、パフォーマンス・オーバーヘッドはわずかなため、本番環境で使用できます。JFRは、実行中のアプリケーションに関する大量のデータを継続的に保存します。このプロファイリング情報には、スレッド・サンプル、ロック・プロファイル、ガベージ・コレクションの詳細などが含まれます。JFRは、論理的にグループ化された表およびチャートに診断情報を示します。これを使用すると、問題に焦点を当てるために必要となる期間および詳細レベルを選択できます。Oracleサポートに連絡する際には、JFRによって収集されたデータが、Javaアプリケーションの問題を診断しやすくするうえで不可欠となる可能性があります。

  • プラグインは、ヒープ・ダンプ分析およびDTrace記録に役立ちます。プラグインの詳細を参照してください。JMCプラグインは、Java Management Extensions (JMX)エージェントを使用してJVMに接続します。JMXの詳細は、『Java Platform, Standard Edition Java Management Extensionsガイド』を参照してください。

JDK Mission Controlによるトラブルシューティング

JMCには、トラブルシューティングに役立つ次の機能があります:

  • Java管理コンソール(JMX)が実行中のJVMに接続し、主な特性をリアルタイムに収集して表示します。
  • JVMのユーザー指定のカスタム・アクションとルールのトリガーを設定します。
  • JMCツールの試験的プラグインは、トラブルシューティング・アクティビティを提供します。
  • JMCでのフライト記録は、イベントの分析に使用できます。事前構成済のタブを使用すると、コード、メモリーとガベージ・コレクション、スレッドとI/Oといったよく使用される様々な領域で簡単にドリルダウンできます。フライト記録の「自動分析結果」ページを使用すると、問題を迅速に診断できます。提供されているルールおよびヒューリスティックは、アプリケーションの機能およびパフォーマンスの問題の検出に役立ち、チューニングのヒントを提供します。セーフ・ポイントなど、比較的知られていない概念を使用するルールの中には、詳細情報への説明とリンクを提供するものがあります。一部のルールはパラメータ化され、特定の環境でより意味のあるものに構成できます。個々のルールは、適合するかどうかに応じて有効化または無効化できます。
    • JMCアプリケーションのフライト・レコーダでは、論理的にグループ化された表、グラフおよびダイアルに診断情報が表示されます。これを使用すると、問題に焦点を当てるために必要となる期間および詳細レベルを選択できます。
  • JMCプラグインは、Java Management Extensions (JMX)エージェントを使用してJVMに接続します。JMXは、アプリケーション、デバイス、サービス、Java仮想マシンなどのリソースを管理およびモニタリングするための標準APIです。

フライト・レコーダ

フライト・レコーダ(JFR)は、JDKに組み込まれているプロファイリングおよびイベント収集のフレームワークです。

フライト・レコーダにより、Javaの管理者および開発者は、JVMおよびJavaアプリケーションの動作状況に関する詳細な下位レベルの情報を収集できます。JMCを使用して、JFRによって収集されたデータを視覚化できます。フライト・レコーダとJMCを組み合せると、完全なツールチェーンとなり、下位レベルの詳細な実行時情報が継続的に収集され、事後のインシデント分析が可能になります。

JFRを使用するメリット:

  • JVMイベントが発生すると、イベントに関するデータがタイムスタンプとともに記録されます。
  • JFRを使用してイベントを記録すると、実行の状態が保存され、問題を分析できます。データにはいつでもアクセスでき、問題をよく理解して解決できます。
  • JFRでは、記録プロセスのオーバーヘッドを低く抑えながら、本番システムに大量のデータを記録できます。
  • レイテンシの記録に最適です。アプリケーションが想定どおりに実行されていない状況が記録され、ボトルネックの詳細が示されます。
  • ハードウェアからオペレーティング・システム、JVM、JDKおよびJavaアプリケーション環境に至るまでの実行環境全体とプログラムがどのように相互作用するかについて洞察が提供されます。

フライト記録は、アプリケーションの起動時、またはアプリケーションの実行中に開始できます。データは、イベントと呼ばれるタイムスタンプ付きのデータ・ポイントとして記録されます。イベントは、次のカテゴリに分類されます:

  • 期間イベント: 特定の開始時間と停止時間の特定の期間に発生します。
  • インスタント・イベント: 即座に発生し、すぐにログに記録されます。たとえば、スレッドのブロックなどです。
  • サンプル・イベント: 定期的な間隔で発生し、システム全体のヘルス状態を確認します。たとえば、ヒープ診断を1分ごとに出力するなどです。
  • カスタム・イベント: JMCまたはAPIを使用して作成されたユーザー定義イベント。

また、記録テンプレートで有効化されている事前定義済イベントがあります。一部のテンプレートは、ごく基本的なイベントのみを保存し、パフォーマンスにほとんど影響を与えません。その他のテンプレートはパフォーマンスに若干のオーバーヘッドを伴い、追加データを収集するためにガベージ・コレクションをトリガーする場合もあります。フライト・レコーダに付属して次のテンプレートが<JDK_ROOT>/lib/jfrディレクトリに提供されます:

  • default.jfc: 低いオーバーヘッドで事前定義済のデータ・セットを収集します。
  • profile.jfc: default.jfcテンプレートよりも多くのデータを提供しますが、オーバーヘッドもパフォーマンスに与える影響もあります。

フライト・レコーダは、次のタイプの記録を生成します:

  • 一定時間の記録: 一定時間の記録はプロファイリング記録とも呼ばれ、設定された時間だけ実行されて停止します。通常、一定時間の記録では有効になるイベントの数が多く、パフォーマンスに多少影響する場合があります。オンになるイベントは、要件に応じて変更できます。一定時間の記録は、自動的にダンプされ、開かれます。

    一定時間の記録の一般的な使用事例は次のとおりです:

    • 最もよく実行されるメソッドおよび最も多くのオブジェクトが作成される場所のプロファイルを記録する。

    • メモリー・リーク発生の指標となる、ヒープ使用量の増加を示しているクラスを探す。

    • 同期に起因するボトルネックおよび多数のこのようなユース・ケースを探す。

  • 連続記録: 連続記録は、常時オンの記録で、たとえば、最後の6時間のデータを保存します。この記録中、JFRはイベントを収集し、データをグローバル・バッファに書き込みます。グローバル・バッファがいっぱいになった場合、最も古いデータが破棄されます。ダンプをリクエストしたり、ルールによってダンプがトリガーされると、現在バッファにあるデータが指定されたファイルに書き込まれます。

    デフォルト・テンプレートでの連続記録はオーバーヘッドが少なく、有益なデータが大量に収集されます。ただし、このテンプレートは、ヒープ統計や割当てプロファイリングを収集しません。

フライト記録の生成

次の項では、フライト記録を作成する様々な方法について説明します。

フライト記録の開始

これらのステップに従って、JMCを使用したフライト記録を開始します。

  1. JVMブラウザでJVMを検索します。
  2. JVMを右クリックし、「フライト記録の開始」を選択します。

    「フライト記録の開始」ウィンドウが開きます。

  3. 「参照」をクリックして、記録の保存に適切な場所とファイル名を検索します。
  4. 「一定時間の記録」(プロファイリング記録)または「連続記録」を選択します。連続記録の場合は、保存するイベントの最大サイズまたは最大保持時間を指定できます。
  5. 「イベント設定」ドロップダウン・リストのフライト記録テンプレートを選択します。テンプレートで、記録するイベントを定義します。独自のテンプレートを作成するには、「テンプレート・マネージャ」をクリックします。ただし、ほとんどの場合、連続テンプレート(記録のオーバーヘッドが非常に低い)またはプロファイリング・テンプレート(より多くのデータと若干のオーバーヘッド)のいずれかが選択されます。
  6. 「完了」をクリックして記録を開始するか、「次」をクリックして選択したテンプレートで定義されているイベント・オプションを変更します。
  7. フライト記録のイベント・オプションを変更します。デフォルトの設定では、データとパフォーマンスのバランスが良くとれています。これらの設定は、要件に基づいて変更できます。

    たとえば:

    • しきい値は、記録イベントの長さです。デフォルトでは、10ミリ秒を超える同期イベントが収集されます。これは、スレッドが10msを超えてロックを待機している場合、イベントが保存されることを意味します。短い競合の詳細データを取得するには、この値を下げることができます。
    • 「スレッド・ダンプ」設定は、定期的なスレッド・ダンプを実行するためのオプションを提供します。これらは通常のテキストのスレッド・ダンプです。
  8. 「完了」をクリックして記録を開始するか、「次」をクリックして選択したテンプレートで定義されているイベント詳細を変更します。
  9. 選択したフライト記録テンプレートのイベント詳細を変更します。イベント詳細は、イベントを記録に含めるかどうかを定義します。一部のイベントでは、スタック・トレースをイベントにアタッチするかどうか、期間しきい値(持続イベントの場合)およびリクエスト期間(リクエスト可能なイベントの場合)を指定することもできます。
  10. 前のステップで設定された設定を変更する場合は「戻る」をクリックし、「終了」をクリックして記録を開始します。
    新しいフライト記録が「進行状況の表示」に表示されます。

    ノート:

    実行中の記録を表示するには、JVMブラウザでノードを展開します。記録のダンプ、記録の全体のダンプ、記録の最後の部分のダンプ、記録の編集、停止またはクローズを行うには、記録を右クリックします。プロファイリング記録を停止しても記録ファイルは作成され、プロファイリング記録を閉じると記録が破棄されます。

ノート:

JMXコンソールの「トリガー」タブを使用して、条件が満たされた場合にフライト記録が自動的に開始されるようJMCを設定できます。詳細は、トリガーを使用した自動フライト記録を参照してください。
トリガーを使用した自動フライト記録

「トリガー」タブでは、特定の条件が満たされた場合に、イベントをトリガーするルールを定義およびアクティブ化できます。たとえば、条件が満たされた場合にフライト記録を自動的に開始するようにJDK Mission Controlを設定できます。これは、特定のJVMランタイムの問題を追跡する場合に有用です。

これはJMXコンソールから実行します。
  1. JMXコンソールを起動するには、JVMブラウザでアプリケーションを見つけてそれを右クリックし、「JMXコンソールの起動」を選択します
  2. 画面下部の「トリガー」タブをクリックします。
  3. 「追加」をクリックします。アプリケーション内の任意のMBean(アプリケーションに固有のMBeanを含む)を選択できます。
    「新規ルールの追加」ダイアログが開きます。
  4. トリガーするルールの属性を選択し、「次へ」をクリックします。たとえば、「java.lang」 > 「OperatingSystem」 > 「ProcessCpuLoad」を選択します。
  5. ルールがトリガーされる条件を設定し、「次」をクリックします。たとえば、「最大トリガー値」「持続期間」および「制限期間」の値を設定します。

    ノート:

    「条件に合致したときにトリガーします。」または「条件から復帰したときにトリガーします」チェック・ボックスを選択できます。
  6. トリガーされたときにルールで実行するアクションを選択し、「次」をクリックします。たとえば、「期限付きフライト記録の開始」を選択し、ファイル宛先および記録時間を参照します。トリガーされたらフライト記録が自動的に開くようにする場合は、「自動的に開く」チェックボックスを選択します。
  7. ルールに対する制約を選択し、「次」をクリックします。たとえば、ルールをアクティブにする特定の日付、曜日または時刻を選択します。
  8. 新しいルールの名前を入力し、「終了」をクリックします。
    ルールが「ルール」リストに追加されます。
「トリガー・ルール」リストからルールを選択すると、「ルールの詳細」ペインの次のタブにそのコンポーネントが表示されます。必要に応じて、条件、属性および制約を編集できます:
  • 条件
  • アクション
  • 制約
コマンド行での起動フラグによるフライト記録の作成

アプリケーションの起動時に記録を開始するには起動フラグを使用します。アプリケーションがすでに実行中の場合は、jcmdユーティリティを使用して記録を開始します。

フライト記録を生成するには、次の方法を使用します。
  • アプリケーションの起動時にプロファイリング記録を生成します。

    -XX:StartFlightRecordingオプションを使用して、アプリケーションの起動時に一定時間の記録を設定できます。次の例は、MyAppアプリケーションを実行し、JVMを起動してから20秒後に60秒間の記録を開始し、それをmyrecording.jfrという名前のファイルに保存する方法を示しています。

    java -XX:StartFlightRecording.delay=20s,duration=60s,name=myrecording,filename=myrecording.jfr,settings=profile MyApp

    設定パラメータは、テンプレートの名前を受け取ります。テンプレートがjava-home/lib/jfrディレクトリ(デフォルト・テンプレートの場所)にない場合は、パスを含めます。標準テンプレートはprofileです。これは、より多くのデータを収集し、主にプロファイリング記録用で、defaultです。主に連続記録用に行われるオーバーヘッドの低い設定です。

    javaコマンドのフライト・レコーダ・フラグの詳細は、Java Development Kitツール仕様Javaの拡張ランタイム・オプションに関する項を参照してください。

  • アプリケーションの起動時に連続記録を生成します。

    -XX:StartFlightRecordingオプションを使用して、コマンド行から連続記録を開始できます。-XX:FlightRecorderOptionsには、記録を管理するための追加設定が用意されています。これらのフラグは、必要に応じて後でダンプできる連続記録を開始します。次の例は、6時間のデータをディスクに保存する連続記録を使用してMyAppアプリケーションを実行する方法を示しています。一時データは/tmpフォルダに保存されます。

    java -XX:StartFlightRecording.disk=true,maxage=6h,settings=default -XX:FlightRecorderOptions=repository=/tmp MyApp

    ノート:

    実際に記録をダンプするときは、ダンプ・ファイルのための新しい場所を指定するので、リポジトリ内のファイルは一時的です。
  • 診断コマンドを使用した記録を生成します。

    実行中のアプリケーションでは、Javaコマンド行診断コマンドを使用して記録を生成できます。診断コマンドを実行する最も単純な方法は、java-home/binディレクトリにあるjcmdツールを使用することです。詳細は、「jcmdユーティリティ」を参照してください。

    次の例は、プロセスIDが5361MyAppアプリケーションの記録を開始する方法を示しています。30分間のデータが記録され、/usr/recording/myapp-recording1.jfrに書き込まれます。

    jcmd 5361 JFR.start duration=30m filename=/usr/recordings/myapp-recording1.jfr

フライト記録の分析

次の項では、フライト記録を分析する様々な方法について説明します。

JMCを使用したフライト記録の分析

フライト記録ファイルをJMCで開くと、コード、メモリー、スレッド、ロック、I/Oなどの様々な領域を参照して、アプリケーションの実行時動作の様々な面を分析できます。

時間が設定された記録が終了するか、実行中の記録のダンプが作成されると、記録ファイルがJMCで自動的に開きます。ダブルクリックするか、「ファイル」メニューを使用して任意の記録ファイルを開くこともできます。フライト記録が「自動分析の結果」ページで開きます。このページは、問題を迅速に診断するのに役立ちます。たとえば、ガベージ・コレクションのチューニングまたはメモリー割当ての問題の追跡などの場合は、メモリー・ビューを使用して、個々のガベージ・コレクション・イベント、割当てサイト、ガベージ・コレクションの一時休止などに関する詳細なビューを取得できます。「I/O」ビューと「スレッド」ビューでアプリケーションのレイテンシ・プロファイルを視覚化できます。また、記録内の個々のイベントを表すビューにドリルダウンすることもできます。

「自動分析の結果」ページの表示

フライト・レコーダでは、記録からデータが抽出および分析され、「自動分析の結果」ページに色分けされたレポート・ログが表示されます。

デフォルトでは、潜在的な問題に注意が向けられるよう、黄色および赤色のスコアの結果が表示されます。レポートにすべての結果を表示するには、ページの右上にある「正常な結果の表示」」ボタン(チェック・マーク)をクリックします。同様に、結果を表として表示するには、「表」ボタンをクリックします。

ベンチマークは、主に次のものに関連する問題に分かれています:

レポートの見出し(たとえば、「Javaアプリケーション」)をクリックすると、対応するページが表示されます。

ノート:

アウトライン・ビューで、各エントリを選択して、自動分析の各ページ間を移動できます。
Javaアプリケーションの分析

「Javaアプリケーション」ダッシュボードには、Javaアプリケーションの全体的なヘルスが表示されます。

黄色および赤色のスコアを持つパラメータに注意を向けてください。ダッシュボードで、問題のある状況を的確にとらえることができます。特定のページに移動し、データを分析したり、問題を修正します。

スレッド

「スレッド」ページでは、Javaアプリケーションに属するすべてのスレッドのスナップショットが提供されます。問題の診断およびアプリケーションとJVMのパフォーマンスの最適化に役立つ、アプリケーションのスレッド・アクティビティに関する情報が表示されます。

スレッドは表に表され、各行にはグラフが関連付けられています。グラフは、問題のある実行パターンの特定に役立ちます。各スレッドの状態は、スタック・トレースとして表示され、問題領域を即時に表示できるコンテキスト情報が提供されます。たとえば、デッドロックの発生を簡単に確認できます。

ロック・インスタンス

「ロック・インスタンス」では、スレッドがロックを取得しようとしていたり、ロックに関する通知を待機しているかどうかなどのロック情報を指定しているスレッドの詳細が提供されます。スレッドがロックを取得すると、詳細がスタック・トレースに表示されます。

メモリー

アプリケーションのパフォーマンスに関する問題を検出する方法の1つは、実行時にメモリーがどのように使用されるかを確認することです。

「メモリー」ページでは、グラフにJavaアプリケーションのヒープ・メモリー使用量が表されます。各サイクルには、ヒープ・メモリーの割当ての期間を表すJavaヒープ増加フェーズがあります。その後、ガベージ・コレクションを表す急な減少があり、サイクルが最初から始まります。グラフから得られる重要な推論は、各サイクルでガベージ・コレクタがヒープを開始位置に押し下げるため、メモリー割当ての期間は短いということです。

「ガベージ・コレクション」チェック・ボックスを選択すると、グラフにガベージ・コレクション一時休止時間が表示されます。これは、ガベージ・コレクタが一時休止時間中にアプリケーションを停止し、作業を行ったことを示します。一時休止時間が長いと、アプリケーションのパフォーマンスが低下するため、対処する必要があります。

メソッド・プロファイリング

「メソッド・プロファイリング」ページでは、特定のメソッドが実行された頻度やメソッドの実行にかかった時間を確認できます。実行に長い時間を要するメソッドを特定することでボトルネックが判明します。

プロファイリングでは大量のデータが生成されるため、デフォルトではオンになっていません。新しい記録を開始し、「イベント設定」ドロップダウン・メニューで「プロファイリング - サーバー上」を選択します。一定時間の記録を短い期間実行します。JFRは、指定されているファイルに記録をダンプします。JMCで「メソッド・プロファイリング」ページを開き、上位の割当てを確認します。上位のパッケージとクラスが表示されます。スタック・トレースで詳細を確認します。コードを調べて、メモリー割当てが特定のオブジェクトに集中しているかどうかを確認します。JFRは、問題が解決していない特定の行番号を指します。

JVM内部

「JVM内部」ページには、JVMとその動作の詳細が表示されます。

確認の必要な最も重要なパラメータの1つは、ガベージ・コレクションです。ガベージ・コレクションとは、未使用のオブジェクトを削除して、その領域を新規オブジェクトの割当てに使用できるようにするプロセスです。「ガベージ・コレクション」ページでは、実行時のシステム動作とガベージ・コレクションのパフォーマンスをよりよく理解できます。

グラフには、一時休止時間と比較したヒープ使用量、および指定した期間におけるヒープ使用量の変化が表示されます。ページには、記録中に発生したすべてのガベージ・コレクション・イベントも表示されます。ヒープに対する最長の一時休止時間を監視します。休止時間は、アプリケーションの処理中にガベージ・コレクションに時間がかかっていることを示します。ガベージ・コレクションによって解放されるヒープの領域が少なくなっていることを意味します。この状況は、メモリー・リークを引き起こす可能性があります。

メモリー管理を効果的に行うには、「コンパイル」ページを確認します。このページには、コード・コンパイルの詳細が期間とともに表示されます。大規模アプリケーションでは、コンパイルされたメソッドが多数存在する場合があり、メモリーが使い果たされてパフォーマンスの問題が発生する可能性があります。

環境

「環境」ページには、記録が行われた環境に関する情報が示されます。CPU使用率、使用されているメモリーおよびオペレーティング・システムについて理解するのに役立ちます。

「プロセス」ページを参照して、実行中の同時プロセスおよびこれらのプロセスの競合CPU使用率を確認します。多数のプロセスがCPUおよびその他のシステム・リソースを使用する場合、アプリケーションのパフォーマンスが影響を受けます。

「イベント・ブラウザ」ページで、すべてのイベント・タイプの統計を確認します。これにより、ボトルネックに着目し、アプリケーションのパフォーマンスを改善するための適切な措置を講じることができます。

「イベント・ブラウザ」ページを使用してカスタム・ページを作成できます。イベント・タイプ・ツリーで必要なイベント・タイプを選択し、ページの右上隅の「選択したイベント・タイプを使用した新しいページの作成」ボタンをクリックします。カスタム・ページが、イベント・ブラウザ・ページの下に新しいイベント・ページとしてリストされます。

jfrツールまたはJFR APIを使用したフライト記録の分析

フライト・レコーダから記録の情報にアクセスするには、jfrツールを使用してイベント情報を出力するか、フライト・レコーダAPIを使用してデータをプログラムで処理します。

フライト・レコーダは、記録された情報を確認するために次の方法を提供します。

  • jfrツール - このコマンド行ツールを使用して、記録からイベント・データを出力します。このツールは、java-home/binディレクトリにあります。このツールの詳細は、Java Development Kitツール仕様jfrコマンドに関する項を参照してください
  • フライト・レコーダAPI - jdk.jfr.consumer APIを使用して、記録内の情報を抽出および書式設定します。詳細は、『Flight Recorder APIプログラマーズ・ガイド』を参照してください。

記録内のイベントを使用して、次の領域を調査できます。

  • 一般情報
    • 各タイム・スタンプで記録されるイベント数

    • 最大ヒープ使用量

    • 時間経過に伴うCPU使用率、アプリケーションのCPU使用率およびCPU使用率合計

      100%近くまで急上昇しているCPU使用率、低すぎるCPU使用率、またはガベージ・コレクションの長すぎる一時休止などに注意してください。

    • GC一時休止時間

    • JVM情報およびシステム・プロパティ・セット

  • メモリー
    • 一定期間のメモリー使用状況

      通常は、一時オブジェクトが絶えず割り当てられています。条件が満たされると、ガベージ・コレクション(GC)がトリガーされ、使用されなくなったすべてのオブジェクトが削除されます。したがって、ヒープ使用量は、GCがトリガーされるまで絶え間なく増加した後、急激に減少します。メモリー・リークを示す可能性がある、徐々に増加しているヒープ・サイズを監視します。

    • ガベージ・コレクションに関する情報(ガベージ・コレクションの実行にかかった時間など)

    • 行われたメモリー割当て

      アプリケーションによる一時オブジェクトの割当てが多いほど、アプリケーションで実行する必要があるガベージ・コレクションが増えます。メモリー割当てを確認すると、ほとんどの割当てを探してアプリケーションでのGC圧力を軽減できます。

    • 最も活発なセットがあるクラス

      フライト記録中の各オブジェクト・タイプのサイズの増加を監視します。特定のオブジェクト・タイプのサイズが大きく増加した場合にはメモリー・リークを示していますが、わずかな変動は正常です。特に、標準Javaクラス以外の上位の増加を調査します。

  • コード
    • 実行時間が最も長いパッケージとクラス

      アプリケーション内のボトルネックを特定するためにメソッドが呼び出される場所を監視します。

    • スローされる例外

    • アプリケーションが実行されている間にコンパイルされたメソッド

    • 一定期間にわたるロード済クラス、実際にロードされたクラスおよびロードされていないクラスの数

  • スレッド
    • 一定期間のCPU使用率およびスレッド数

    • コード実行の大半を行うスレッド

    • 同期のために最も待機しているオブジェクト

  • I/O
    • ファイルの読取り、ファイルの書込み、ソケットの読取りおよびソケットの書込みに関する情報

  • システム
    • アプリケーションが実行されているマシンのCPU、メモリーおよびOSに関する情報

    • 環境変数およびJVMと同時に実行されている他のプロセス

  • イベント
    • 記録内のすべてのイベント

jcmdユーティリティ

jcmdユーティリティは、JVMに診断コマンド要求を送信する際に使用されます。これらのリクエストは、フライト・レコーダからの記録の管理、JVMおよびJavaアプリケーションのトラブルシューティングと診断に役立ちます。

jcmdはJVMが実行されているものと同じマシン上で使用され、JVMの起動で使用されたものと同じ有効なユーザーおよびグループ識別子を持っている必要があります。

特殊コマンドjcmd <process id/main class> PerfCounter.printは、プロセス内のすべてのパフォーマンス・カウンタを出力します。

コマンドjcmd <process id/main class> <command> [options]は、JVMにコマンドを送信します。

次の例に、jcmdユーティリティによるJVMへの診断コマンド・リクエストを示します。

> jcmd
5485 jdk.jcmd/sun.tools.jcmd.JCmd
2125 MyProgram
 
> jcmd MyProgram (or "jcmd 2125")
2125:
The following commands are available:
Compiler.CodeHeap_Analytics
Compiler.codecache
Compiler.codelist
Compiler.directives_add
Compiler.directives_clear
Compiler.directives_print
Compiler.directives_remove
Compiler.queue
GC.class_histogram
GC.class_stats
GC.finalizer_info
GC.heap_dump
GC.heap_info
GC.run
GC.run_finalization
JFR.check
JFR.configure
JFR.dump
JFR.start
JFR.stop
JVMTI.agent_load
JVMTI.data_dump
ManagementAgent.start
ManagementAgent.start_local
ManagementAgent.status
ManagementAgent.stop
Thread.print
VM.class_hierarchy
VM.classloader_stats
VM.classloaders
VM.command_line
VM.dynlibs
VM.events
VM.flags
VM.info
VM.log
VM.metaspace
VM.native_memory
VM.print_touched_methods
VM.set_flag
VM.stringtable
VM.symboltable
VM.system_properties
VM.systemdictionary
VM.uptime
VM.version
help

For more information about a specific command use 'help <command>'.

> jcmd MyProgram help Thread.print
2125:
Thread.print
Print all threads with stacktraces.
 
Impact: Medium: Depends on the number of threads.
 
Permission: java.lang.management.ManagementPermission(monitor)
 
Syntax : Thread.print [options]
 
Options: (options must be specified using the <key> or <key>=<value> syntax)
        -l : [optional] print java.util.concurrent locks (BOOLEAN, false)
        -e : [optional] print extended thread information (BOOLEAN, false)
 
> jcmd MyProgram Thread.print
2125:
2020-01-21 17:05:10
Full thread dump Java HotSpot(TM) 64-Bit Server VM (14-ea+29-1384 mixed mode):
...

次の項では、jcmdユーティリティでの便利なコマンドおよびトラブルシューティング手法について説明します。

jcmdユーティリティの有用なコマンド

使用可能な診断コマンドは、使用するJVMによって異なります。jcmd <process id/main class> helpを使用すると、使用可能なすべてのオプションが表示されます。

jcmdツールの非常に役立つコマンドの一部を次に示します。

  • HotSpotおよびJDKのバージョンIDの出力
    jcmd <process id/main class> VM.version
  • VMに設定されているすべてのシステム・プロパティの出力

    数百行の情報が表示される可能性があります。

    jcmd <process id/main class> VM.system_properties

  • VMで使用されるすべてのフラグの出力

    フラグを指定していない場合でも、いくつかのデフォルト値(初期ヒープ・サイズや最大ヒープ・サイズなど)が表示されます。

    jcmd <process id/main class> VM.flags

  • 稼働時間(秒)の出力

    jcmd <process id/main class> VM.uptime

  • クラス・ヒストグラムの作成

    出力結果が冗長になる可能性があるので、出力をファイルにリダイレクトできます。内部クラスとアプリケーション固有のクラスの両方がリストに含まれます。メモリーの消費量が最も多いクラスから降順に表示されます。

    jcmd <process id/main class> GC.class_histogram

  • ヒープ・ダンプの作成

    jcmd GC.heap_dump filename=Myheapdump

    これはjmap -dump:file=<file> <pid>を使用する方法と同じですが、推奨ツールはjcmdです。

  • ヒープ・ヒストグラムの作成

    jcmd <process id/main class> GC.class_histogram filename=Myheaphistogram

    これはjmap -histo <pid>を使用する方法と同じですが、推奨ツールはjcmdです。

  • スタック・トレースのあるすべてのスレッドの出力

    jcmd <process id/main class> Thread.print

jcmdコマンド・ユーティリティを使用したトラブルシューティング

jcmdは、実行中のJava仮想マシン(JVM)またはJavaアプリケーションに診断コマンド要求を送信する場合に使用します。

jcmdユーティリティでは、次のトラブルシューティング・オプションを使用できます。

  • フライト・レコーダで記録を開始します。

    たとえば、識別子が7060の実行中Javaプロセスで2分間の記録を開始し、それをC:\TEMP\myrecording.jfrに保存するには、次を使用します。

    jcmd 7060 JFR.start name=MyRecording settings=profile delay=20s duration=2m filename=C:\TEMP\myrecording.jfr

  • 記録の確認

    JFR.check診断コマンドは、実行中の記録を確認します。たとえば:

    jcmd 7060 JFR.check

  • 記録の停止

    JFR.stop診断コマンドは、実行中の記録を停止し、記録データを破棄することもできます。たとえば:

    jcmd 7060 JFR.stop

  • 記録のダンプ

    JFR.dump診断コマンドは、実行中の記録を停止し、記録をファイルにダンプすることもできます。たとえば:

    jcmd 7060 JFR.dump name=MyRecording filename=C:\TEMP\myrecording.jfr

  • ヒープ・ダンプの作成

    ヒープ・ダンプを作成する推奨方法を次に示します。

    jcmd <pid> GC.heap_dump filename=Myheapdump

  • ヒープ・ヒストグラムの作成

    ヒープ・ヒストグラムを作成する推奨方法を次に示します。

    jcmd <pid> GC.class_histogram filename=Myheaphistogram

ネイティブ・メモリー・トラッキング

ネイティブ・メモリー・トラッキング(NMT)は、Java HotSpot VMの内部メモリー使用状況を追跡するJava HotSpot VM機能です。

NMTでは、非JVMコードによるメモリーの割当てを追跡しないので、ネイティブ・コードのメモリー・リークを検出するには、オペレーティング・システムでサポートされたツールの使用が必要になる場合があります。

次の項では、VM内部メモリー割当てのモニターおよびVMメモリー・リークの診断方法について説明します。

VM内部メモリーをモニターする方法

ネイティブ・メモリー・トラッキングはメモリーをモニターし、開発またはメンテナンス時にアプリケーションのメモリー使用量が増え始めないように設定できます。

NMTのメモリー・カテゴリの詳細は、表2-1を参照してください。

次の項では、NMTのサマリーまたは詳細データを取得する方法、およびサンプル出力の解釈の方法を説明します。

  • サンプル出力の解釈: 次のサンプル出力から、予約済メモリーとコミット済メモリーを確認できます。コミット済メモリーのみが実際に使用されることに注意してください。たとえば、-Xms100m -Xmx1000mで実行した場合、JVMでは1000MBがJavaヒープ用に予約されます。初期のヒープ・サイズは100MBのみであるため、最初に100MBのみがコミットされます。アドレス領域がほぼ無制限である64ビット・マシンの場合、JVMで多くのメモリーが予約されても問題はありません。コミットされるメモリーが次第に増加し、スワッピングやネイティブ・メモリー不足(OOM)状態になる可能性がある場合に、問題が発生します。

    アリーナは、mallocを使用して割り当てられるメモリー・チャンクです。スコープを終了またはコード領域を離れるとき、これらのチャンクからメモリーがバルクで解放されます。これらのチャンクは、一時メモリーを保持するために他のサブシステムで再利用できます(プリスレッドの割当てなど)。アリーナのmallocポリシーでは、メモリー・リークがないことが確認されます。したがって、個々のオブジェクトではなく、Arena全体が追跡されます。一部の初期メモリーは追跡できません。

    NMTを有効にすると、JVMパフォーマンスが5-10%低下し、NMTのメモリー使用量により、すべてのmallocメモリーに2マシン・ワードがmallocヘッダーとして追加されます。NMTのメモリー使用量も、NMTにより追跡されます。

    >jcmd 17320 VM.native_memory
    Native Memory Tracking:
    
    Total: reserved=5699702KB, committed=351098KB
    -                 Java Heap (reserved=4153344KB, committed=260096KB)
                                (mmap: reserved=4153344KB, committed=260096KB)
    
    -                     Class (reserved=1069839KB, committed=22543KB)
                                (classes #3554)
                                (  instance classes #3294, array classes #260)
                                (malloc=783KB #7965)
                                (mmap: reserved=1069056KB, committed=21760KB)
                                (  Metadata:   )
                                (    reserved=20480KB, committed=18944KB)
                                (    used=18267KB)
                                (    free=677KB)
                                (    waste=0KB =0.00%)
                                (  Class space:)
                                (    reserved=1048576KB, committed=2816KB)
                                (    used=2454KB)
                                (    free=362KB)
                                (    waste=0KB =0.00%)
    
    -                    Thread (reserved=24685KB, committed=1205KB)
                                (thread #24)
                                (stack: reserved=24576KB, committed=1096KB)
                                (malloc=78KB #132)
                                (arena=30KB #46)
    
    -                      Code (reserved=248022KB, committed=7890KB)
                                (malloc=278KB #1887)
                                (mmap: reserved=247744KB, committed=7612KB)
    
    -                        GC (reserved=197237KB, committed=52789KB)
                                (malloc=9717KB #2877)
                                (mmap: reserved=187520KB, committed=43072KB)
    
    -                  Compiler (reserved=148KB, committed=148KB)
                                (malloc=19KB #95)
                                (arena=129KB #5)
    
    -                  Internal (reserved=735KB, committed=735KB)
                                (malloc=663KB #1914)
                                (mmap: reserved=72KB, committed=72KB)
    
    -                     Other (reserved=48KB, committed=48KB)
                                (malloc=48KB #4)
    
    -                    Symbol (reserved=4835KB, committed=4835KB)
                                (malloc=2749KB #17135)
                                (arena=2086KB #1)
    
    -    Native Memory Tracking (reserved=539KB, committed=539KB)
                                (malloc=8KB #109)
                                (tracking overhead=530KB)
    
    -               Arena Chunk (reserved=187KB, committed=187KB)
                                (malloc=187KB)
    
    -                   Logging (reserved=4KB, committed=4KB)
                                (malloc=4KB #179)
    
    -                 Arguments (reserved=18KB, committed=18KB)
                                (malloc=18KB #467)
    
    -                    Module (reserved=62KB, committed=62KB)
                                (malloc=62KB #1060)
  • 詳細データの取得: ネイティブ・メモリー使用量の詳細ビューを取得するには、次のコマンドライン・オプションを使用してJVMを起動します: -XX:NativeMemoryTracking=detailこれは、最も多くのメモリーを割り当てるメソッドを正確に追跡します。NMTを有効にすると、JVMパフォーマンスが5-10%低下し、NMTのメモリー使用量により、すべてのmallocメモリーに2ワードがmallocヘッダーとして追加されます。NMTのメモリー使用量も、NMTにより追跡されます。

    次の例は、追跡レベルが詳細に設定された仮想メモリーの出力例です。これは、前述のサマリー出力に加えて表示されます。このサンプル出力を得るための1つの方法は、jcmd <pid> VM.native_memory detailを実行することです。

    Virtual memory map:
    
    [0x00000000a1000000 - 0x0000000800000000] reserved 30916608KB for Java Heap from
        [0x00007f5b91a2472b] ReservedHeapSpace::try_reserve_heap(unsigned long, unsigned long, bool, char*)+0x20b
        [0x00007f5b91a24de9] ReservedHeapSpace::initialize_compressed_heap(unsigned long, unsigned long, bool)+0x5a9
        [0x00007f5b91a254c6] ReservedHeapSpace::ReservedHeapSpace(unsigned long, unsigned long, bool, char const*)+0x176
        [0x00007f5b919da835] Universe::reserve_heap(unsigned long, unsigned long)+0x65
    
                   [0x00000000a1000000 - 0x0000000117000000] committed 1933312KB from
                [0x00007f5b9132c9be] G1PageBasedVirtualSpace::commit(unsigned long, unsigned long)+0x18e
                [0x00007f5b913414d1] G1RegionsLargerThanCommitSizeMapper::commit_regions(unsigned int, unsigned long, WorkGang*)+0x1a1
                [0x00007f5b913d5c78] HeapRegionManager::commit_regions(unsigned int, unsigned long, WorkGang*)+0x58
                [0x00007f5b913d6c45] HeapRegionManager::expand(unsigned int, unsigned int, WorkGang*)+0x35
    
                   [0x00000007fe000000 - 0x00000007fef00000] committed 15360KB from
                [0x00007f5b9132c9be] G1PageBasedVirtualSpace::commit(unsigned long, unsigned long)+0x18e
                [0x00007f5b913414d1] G1RegionsLargerThanCommitSizeMapper::commit_regions(unsigned int, unsigned long, WorkGang*)+0x1a1
                [0x00007f5b913d5c78] HeapRegionManager::commit_regions(unsigned int, unsigned long, WorkGang*)+0x58
                [0x00007f5b913d7355] HeapRegionManager::expand_exact(unsigned int, unsigned int, WorkGang*)+0xd5
    
  • NMTベースラインからの差分の取得: サマリーおよび詳細レベルの追跡では、アプリケーションが起動され実行された後、ベースラインを設定できます。これを行うには、アプリケーションのウォーム・アップ後にjcmd <pid> VM.native_memory baselineを実行します。次に、jcmd <pid> VM.native_memory summary.diffまたはjcmd <pid> VM.native_memory detail.diffを実行できます。

    次の例は、ベースラインの設定以降に使用されたネイティブ・メモリー使用量の差分サマリーのサンプル出力で、カテゴリ別のメモリー使用量の変化を示しています:

    Native Memory Tracking:
    
    Total: reserved=33485260KB +28KB, committed=497784KB +96KB
    
    -                 Java Heap (reserved=30916608KB, committed=393216KB)
                                (mmap: reserved=30916608KB, committed=393216KB)
     
    -                     Class (reserved=1048702KB, committed=254KB)
                                (classes #507)
                                (  instance classes #421, array classes #86)
                                (malloc=126KB #635)
                                (mmap: reserved=1048576KB, committed=128KB)
                                (  Metadata:   )
                                (    reserved=8192KB, committed=192KB)
                                (    used=118KB)
                                (    free=74KB)
                                (    waste=0KB =0.00%)
                                (  Class space:)
                                (    reserved=1048576KB, committed=128KB)
                                (    used=5KB)
                                (    free=123KB)
                                (    waste=0KB =0.00%)
     
    -                    Thread (reserved=35984KB, committed=1432KB +68KB)
                                (thread #0)
                                (stack: reserved=35896KB, committed=1344KB +68KB)
                                (malloc=49KB #212)
                                (arena=39KB #68)
     
    -                      Code (reserved=247729KB, committed=7593KB)
                                (malloc=45KB #438)
                                (mmap: reserved=247684KB, committed=7548KB)
     
    -                        GC (reserved=1209971KB, committed=77267KB)
                                (malloc=29183KB #872)
                                (mmap: reserved=1180788KB, committed=48084KB)
     
    -                  Compiler (reserved=168KB, committed=168KB)
                                (malloc=3KB #34)
                                (arena=165KB #5)
    

    次の例は、ベースライン以降に使用されたネイティブ・メモリー使用量の差分詳細を示すサンプル出力で、特定のメモリー・リークを見つけるのに優れた方法です:

    [0x00007f5b9175ea8b] MemBaseline::aggregate_virtual_memory_allocation_sites()+0x11b
    [0x00007f5b9175ed68] MemBaseline::baseline_allocation_sites()+0x188
    [0x00007f5b9175efff] MemBaseline::baseline(bool)+0x1cf
    [0x00007f5b917d19a4] NMTDCmd::execute(DCmdSource, Thread*)+0x2b4
                                 (malloc=1KB type=Native Memory Tracking +1KB #18 +18)
    
    [0x00007f5b917635b0] MallocAllocationSiteWalker::do_malloc_site(MallocSite const*)+0x40
    [0x00007f5b91740bc8] MallocSiteTable::walk_malloc_site(MallocSiteWalker*)+0x78
    [0x00007f5b9175ec32] MemBaseline::baseline_allocation_sites()+0x52
    [0x00007f5b9175efff] MemBaseline::baseline(bool)+0x1cf
                                 (malloc=11KB type=Native Memory Tracking +10KB #156 +136)
    
    [0x00007f5b91a2472b] ReservedHeapSpace::try_reserve_heap(unsigned long, unsigned long, bool, char*)+0x20b
    [0x00007f5b91a24de9] ReservedHeapSpace::initialize_compressed_heap(unsigned long, unsigned long, bool)+0x5a9
    [0x00007f5b91a254c6] ReservedHeapSpace::ReservedHeapSpace(unsigned long, unsigned long, bool, char const*)+0x176
    [0x00007f5b919da835] Universe::reserve_heap(unsigned long, unsigned long)+0x65
                                 (mmap: reserved=30916608KB, committed=475136KB +81920KB Type=Java Heap)
    
    [0x00007f5b91804557] thread_native_entry(Thread*)+0xe7
                                 (mmap: reserved=34868KB, committed=1224KB +68KB Type=Thread Stack)
    
    [0x00007f5b91a23c63] ReservedSpace::ReservedSpace(unsigned long, unsigned long)+0x213
    [0x00007f5b912df57c] G1CollectedHeap::create_aux_memory_mapper(char const*, unsigned long, unsigned long)+0x3c
    [0x00007f5b912e4f13] G1CollectedHeap::initialize()+0x333
    [0x00007f5b919da5dd] universe_init()+0xbd
                                 (mmap: reserved=483072KB, committed=7424KB +1280KB Type=GC)
    
    [0x00007f5b91a23c63] ReservedSpace::ReservedSpace(unsigned long, unsigned long)+0x213
    [0x00007f5b912df57c] G1CollectedHeap::create_aux_memory_mapper(char const*, unsigned long, unsigned long)+0x3c
    [0x00007f5b912e4e6a] G1CollectedHeap::initialize()+0x28a
    [0x00007f5b919da5dd] universe_init()+0xbd
                                 (mmap: reserved=60384KB, committed=928KB +160KB Type=GC)

NMTによるメモリー・リークの検出

ネイティブ・メモリー・トラッキングを使用してメモリー・リークを検知する手順。

メモリー・リークを検出するには、次のステップを実行します。

  1. 次のコマンドライン・オプションを使用して、サマリーまたは詳細なトラッキングが指定されたJVMを起動します: -XX:NativeMemoryTracking=summaryまたは-XX:NativeMemoryTracking=detail
  2. 初期のベースラインを設定します。NMTベースライン機能を使用して、開発とメンテナンスのときに比較するベースラインを取得するには、次を実行します: jcmd <pid> VM.native_memory baseline
  3. 次を使用して、メモリーの変更をモニターします: jcmd <pid> VM.native_memory detail.diff
  4. アプリケーションのメモリー・リークが少量の場合、それが明らかになるまで時間がかかる場合があります。

NMTのメモリー・カテゴリ

NMTで使用されるネイティブ・メモリー・トラッキングのメモリー・カテゴリのリスト。

表2-1に、NMTで使用されるネイティブ・メモリー・カテゴリを示します。これらのカテゴリは、リリースにより変更される可能性があります。

表2-1 ネイティブ・メモリー・トラッキングのメモリー・カテゴリ

カテゴリ 説明

Javaヒープ

オブジェクトが存在するヒープ

クラス

クラス・メタデータ

スレッド

スレッド・データ構造、リソース領域、ハンドル領域などを含む、スレッドによって使用されるメモリー

コード

生成されたコード

GC

カード表など、GCにより使用されるデータ

コンパイラ

コードを生成するときにコンパイラによって使用されるメモリー・トラッキング

内部

コマンドライン・パーサー、JVMTI、プロパティおよびその他によって使用されるメモリーなど、前述のカテゴリに該当しないメモリー

その他

別のカテゴリで扱われていないメモリー

記号

記号用のメモリー

ネイティブ・メモリー・トラッキング

NMTによって使用されるメモリー

アリーナ・チャンク

アリーナのチャンク・プール内のチャンクによって使用されるメモリー

ロギング

ロギングによって使用されるメモリー

引数

引数用のメモリー

モジュール

モジュールによって使用されるメモリー

JConsole

JDKダウンロードに含まれるもう1つの便利なツールは、JConsoleモニタリング・ツールです。このツールはJMXに準拠しています。このツールは、JVMの組込みJMXインストゥルメンテーションを使用して、実行中のアプリケーションのパフォーマンスやリソース消費に関する情報を提供します。

JConsoleツールは、スレッド使用量やメモリー消費量などの有用な情報、およびクラス・ロード、実行時コンパイル、オペレーティング・システムに関する詳細情報を表示する目的で、任意のJavaアプリケーションに接続できます。

この出力は、メモリー・リーク、過剰なクラス・ロードや実行中のスレッドなどの問題の高レベルの診断に役立ちます。これは、チューニングやヒープ・サイズ決定にも役立つ可能性があります。

JConsoleを使用すれば、モニタリングだけでなく、実行中のシステム内のいくつかのパラメータを動的に変更することもできます。たとえば、-verbose:gcオプションの設定を変更できるので、実行中のアプリケーションに対するガベージ・コレクションのトレース出力を動的に有効または無効にできます。

次の項では、JConsoleツールによるトラブルシューティング手法について説明します。

JConsoleツールによるトラブルシューティング

JConsoleを使用して、データをモニターします。

次のリストは、JConsoleツールを使用してモニターできるデータの概要を示しています。各見出しはツール内のタブ・ペインに対応しています。

  • 概要

    このペインには、ヒープ・メモリー使用量、スレッド数、クラス数、およびCPU使用率の経時的推移を示すグラフが表示されます。この概要では、いくつかのリソースのアクティビティを一度に視覚化できます。

  • メモリー

    • 選択された1つのメモリー領域(ヒープ、非ヒープ、各種メモリー・プール)について

      • メモリー使用量の経時的推移を示すグラフ

      • 現在のメモリー・サイズ

      • コミットされたメモリーの量

      • 最大メモリー・サイズ

    • ガベージ・コレクタの情報(実行されたコレクションの回数や、ガベージ・コレクションの実行に費やされた合計時間など)

    • 現在使用中のヒープおよび非ヒープ・メモリーのパーセントを示すグラフ

    さらにこのペインでは、ガベージ・コレクションの実行を要求できます。

  • スレッド

    • スレッド使用量の経時的推移を示すグラフ。

    • ライブ・スレッド: 現在のライブ・スレッド数。

    • ピーク: JVM起動後のライブ・スレッドの最大数。

    • 選択された1つのスレッドの名前、状態、およびスタック・トレース、およびブロックされたスレッドの場合は、スレッドが獲得を待機しているシンクロナイザとロックを所有しているスレッド。

    • デッドロックの検出」ボタンは、デッドロック検出を実行する要求をターゲット・アプリケーションに送信し、各デッドロック・サイクルをそれぞれ異なるタブに表示します。

  • クラス

    • ロード済クラス数の経時的推移を示すグラフ

    • 現在メモリーにロードされているクラスの数

    • JVMの起動後にメモリーにロードされたクラスの合計数(その後アンロードされたものも含む)

    • JVMの起動後にメモリーからアンロードされたクラスの合計数

  • VMサマリー

    • 一般的な情報(JConsole接続データ、JVMの稼働時間、JVMで消費されたCPU時間、コンパイラ名、合計コンパイル時間など)。

    • スレッドおよびクラスのサマリー情報

    • メモリーおよびガベージ・コレクションの情報(ファイナライズ保留中のオブジェクトの数など)

    • オペレーティング・システムに関する情報(物理特性、実行中のプロセス用の仮想メモリー量、スワップ領域など)

    • JVM自体に関する情報(引数やクラス・パスなど)

  • MBeans

    このペインには、接続済のJMXエージェントに登録されたすべてのプラットフォームおよびアプリケーションMBeanを示すツリー構造が表示されます。ツリー内でMBeanを選択すると、その属性、操作、通知、およびその他の情報が表示されます。

    • 操作(存在する場合)を呼び出せます。たとえば、com.sun.managementドメインに含まれるHotSpotDiagnostic MBeanの操作dumpHeapは、ヒープ・ダンプを実行します。この操作の入力パラメータは、ターゲットVMが実行されているマシン上でのヒープ・ダンプ・ファイルのパス名になります。

    • 書込み可能な属性値を設定できます。たとえば、特定のVMフラグの値を設定、設定解除、または変更するには、HotSpotDiagnostic MBeanのsetVMOption操作を呼び出します。フラグは、DiagnosticOptions属性の値のリストによって示されます。

    • 通知(存在する場合)をサブスクライブするには、「サブスクライブ」および「サブスクライブ解除」ボタンを使用します。

JConsoleによるローカルおよびリモート・アプリケーションのモニター

JConsoleは、ローカル・アプリケーションとリモート・アプリケーションの両方をモニターできます。接続先JMXエージェントを指定する引数付きでツールを起動した場合、ツールは指定されたアプリケーションのモニタリングを自動的に開始します。

ローカル・アプリケーションをモニターするには、コマンドjconsolepid (pidはアプリケーションのプロセスID)を実行します。

リモート・アプリケーションをモニターするには、コマンドjconsolehostname: portnumber (hostnameはアプリケーションを実行しているホストの名前、portnumberはJMXエージェントの有効化時に指定したポート番号)を実行します。

jconsoleコマンドを引数なしで実行した場合、このツールはまず、モニター対象のローカルまたはリモート・プロセスを指定するための「新規接続」ウィンドウを表示します。「接続」メニューを使えば別のホストにいつでも接続できます。

最新のJDKリリースでは、モニター対象アプリケーションを起動する際にオプションは不要です。

モニタリング・ツールの出力例として、図2-1はヒープ・メモリー使用量のグラフを示しています。

図2-1 JConsoleからのサンプル出力

図2-1の説明が続きます
「図2-1 JConsoleからのサンプル出力」の説明

jdbユーティリティ

jdbユーティリティは、コマンド行デバッガの例としてJDKに含まれています。jdbユーティリティは、Java Debug Interface (JDI)を使ってターゲットJVMを起動または接続します。

JDIは、(通常はリモートの)仮想マシンの実行状態にアクセスする必要があるデバッガや同様のシステムに役立つ情報を提供する、高レベルのJava APIです。JDIはJava Platform Debugger Architecture (JPDA)のコンポーネントです。「Java Platform Debugger Architecture」を参照してください。

次の項では、jdbユーティリティのトラブルシューティング手法を提供します。

jdbユーティリティによるトラブルシューティング

jdbユーティリティはリモート・デバッグに使用するデバッガ・コネクタをモニターするために使用します。

JDIでは、コネクタを使用してデバッガをターゲットJVMに接続します。JDKには従来、ターゲットJVMとのデバッグ・セッションを開始して確立するコネクタと、(TCP/IPまたは共有メモリー・トランスポートを使用した)リモート・デバッグに使用されるコネクタが付属しています。

これらのコネクタは通常、NetBeans統合開発環境(IDE)や商用IDEなどのエンタープライズ・デバッガで使用されます。

コマンドjdb -listconnectorsは、使用可能なコネクタの一覧を出力します。コマンドjdb -helpは、コマンドの使用方法のヘルプを出力します。

Java Development Kitツール仕様jdbコマンドに関する項を参照してください

jinfoユーティリティ

jinfoコマンド行ユーティリティは、実行中のJavaプロセスまたはクラッシュ・ダンプから構成情報を取得し、JVMの起動時に使用されたシステム・プロパティまたはコマンド行フラグを出力します。

JVMおよびJavaアプリケーションに関する問題を診断するには、JDK Mission Control、フライト・レコーダおよびjcmdユーティリティを使用できます。診断機能を強化し、パフォーマンスのオーバーヘッドを削減するには、以前のjinfoユーティリティのかわりに最新のユーティリティjcmdを使用してください。

jinfoユーティリティの-flagオプションを使用すれば、指定されたJavaプロセスの特定のJVMフラグの値を動的に設定、設定解除、または変更できます。「Java HotSpot VMコマンド行オプション」を参照してください。

次の例は、PID番号が19256のJavaプロセスのjinfoユーティリティの出力を示しています。

c:\Program Files\Java\jdk-13\bin>jinfo 19256
Java System Properties:
java.specification.version=13
sun.cpu.isalist=amd64
sun.jnu.encoding=Cp1252
sun.awt.enableExtraMouseButtons=true
java.class.path=C\:\\sampleApps\\DynamicTreeDemo\\dist\\DynamicTreeDemo.jar
java.vm.vendor=Oracle Corporation
sun.arch.data.model=64
user.variant=
java.vendor.url=https\://java.oracle.com/
os.name=Windows 10
java.vm.specification.version=13
sun.java.launcher=SUN_STANDARD
user.country=US
sun.boot.library.path=C\:\\Program Files\\Java\\jdk-13\\bin
sun.java.command=C\:\\sampleApps\\DynamicTreeDemo\\dist\\DynamicTreeDemo.jar
jdk.debug=release
sun.cpu.endian=little
user.home=C\:\\Users\\user1
user.language=en
java.specification.vendor=Oracle Corporation
java.version.date=2019-09-17
java.home=C\:\\Program Files\\Java\\jdk-13
file.separator=\\
java.vm.compressedOopsMode=Zero based
line.separator=\r\n
java.specification.name=Java Platform API Specification
java.vm.specification.vendor=Oracle Corporation
user.script=
sun.management.compiler=HotSpot 64-Bit Tiered Compilers
java.runtime.version=13-ea+29
user.name=user1
path.separator=;
os.version=10.0
java.runtime.name=Java(TM) SE Runtime Environment
file.encoding=Cp1252
java.vm.name=Java HotSpot(TM) 64-Bit Server VM
java.vendor.url.bug=https\://bugreport.java.com/bugreport/
java.io.tmpdir=C\:\\Users\\user1\\AppData\\Local\\Temp\\
java.version=13-ea
user.dir=C\:\\Users\\user1
os.arch=amd64
java.vm.specification.name=Java Virtual Machine Specification
sun.os.patch.level=
java.library.path=C\:\\Program Files\\Java\\jdk-13\\bin;....
java.vm.info=mixed mode, sharing
java.vendor=Oracle Corporation
java.vm.version=13-ea+29
sun.io.unicode.encoding=UnicodeLittle
java.class.version=57.0

VM Flags:

次のトピックでは、jinfoユーティリティによるトラブルシューティング手法について説明します。

jinfoユーティリティによるトラブルシューティング

jinfoの出力には、java.class.pathおよびsun.boot.class.pathの設定が表示されます。

ターゲットJVMを-classpathおよび-Xbootclasspath引数付きで起動した場合、jinfoの出力にはjava.class.pathsun.boot.class.pathの設定が含まれます。この情報は、クラス・ローダーの問題を調査する際に必要となる可能性があります。

jhsdb jinfoツールは、プロセスから情報を取得するだけでなく、コア・ファイルを入力として使用できます。たとえば、Linuxオペレーティング・システムの場合、前述の例ではgcoreユーティリティを使用してプロセスのコア・ファイルを取得できます。コア・ファイルの名前はcore.19256となり、プロセスの作業ディレクトリ内に生成されます。次の例に示すように、Java実行可能ファイルとコア・ファイルへのパスを、jhsdb jinfoユーティリティの引数として指定する必要があります。

$ jhsdb jinfo --exe java-home/bin/java --core core.19256

バイナリ名はjavaでないことがあります。これは、JNI呼び出しAPIを使用してVMが作成されたときに発生します。jhsdb jinfoツールでは、コア・ファイルの生成元のバイナリが必要です。

jmapユーティリティ

jmapコマンド行ユーティリティは、実行中のVMまたはコア・ファイルのメモリー関係の統計を出力します。コア・ファイルには、jhsdb jmapを使用します。

JVMおよびJavaアプリケーションに関する問題を診断するには、JDK Mission Control、フライト・レコーダおよびjcmdユーティリティを使用できます。診断機能を強化し、パフォーマンスのオーバーヘッドを削減するには、以前のjmapユーティリティのかわりに最新のユーティリティjcmdの使用をお薦めします。

プロセスまたはコア・ファイルでコマンド行オプションなしでjmapを使用された場合、ロードされた共有オブジェクトの一覧が出力されます。より詳細な情報を得るために、オプション-heap-histoまたは-clstatsを使用できます。これらのオプションについては、以降の各サブセクションで説明します。

さらに、JDK 7リリースで導入された-dump:format=b,file=filenameオプションを使用すると、jmapによって、Javaヒープが指定されたファイルにバイナリ形式でダンプされます。

ハングアップ・プロセスが原因でjmap pidコマンドが反応しない場合は、jhsdb jmapユーティリティを使用してServiceability Agentを実行します。

次の項では、トラブルシューティング手法について説明し、実行中のVMまたはコア・ファイルのメモリー関連の統計情報を出力する例を示します。

ヒープの構成と使用量

jhsdb jmap --heapコマンドを使用してJavaヒープ情報を取得します。

次のJavaヒープ情報を取得するには、--heapオプションを使用します。

  • ガベージ・コレクション(GC)アルゴリズムに固有の情報。GCアルゴリズムの名前(パラレルGCなど)やアルゴリズム固有の詳細(パラレルGCのスレッド数など)が含まれます。

  • コマンド行オプションとして指定されたか、またはマシンの構成に基づいてVMによって選択された可能性のあるヒープ構成。

  • ヒープ使用量のサマリー: このツールは、各世代(ヒープ領域)について、合計ヒープ容量、使用中のメモリー、および使用可能な空きメモリーを出力します。領域の集まりとして構成された世代(New世代など)では、領域固有のメモリー・サイズ・サマリーが含まれます。

次の例は、jhsdb jmap --heapコマンドの出力を示しています。

c:\Program Files\Java\jdk-13\bin>jhsdb jmap --heap --pid 19256
Attaching to process ID 19256, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 13-ea+29

using thread-local object allocation.
Garbage-First (G1) GC with 4 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 4253024256 (4056.0MB)
   NewSize                  = 1363144 (1.2999954223632812MB)
   MaxNewSize               = 2551185408 (2433.0MB)
   OldSize                  = 5452592 (5.1999969482421875MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 1048576 (1.0MB)

Heap Usage:
G1 Heap:
   regions  = 4056
   capacity = 4253024256 (4056.0MB)
   used     = 7340032 (7.0MB)
   free     = 4245684224 (4049.0MB)
   0.17258382642998027% used
G1 Young Generation:
Eden Space:
   regions  = 7
   capacity = 15728640 (15.0MB)
   used     = 7340032 (7.0MB)
   free     = 8388608 (8.0MB)
   46.666666666666664% used
Survivor Space:
   regions  = 0
   capacity = 0 (0.0MB)
   used     = 0 (0.0MB)
   free     = 0 (0.0MB)
   0.0% used
G1 Old Generation:
   regions  = 0
   capacity = 250609664 (239.0MB)
   used     = 0 (0.0MB)
   free     = 250609664 (239.0MB)
   0.0% used

ヒープ・ヒストグラム

-histoオプションを指定してjmapコマンドを使用するか、jhsdb jmap --histoコマンドを使用すると、クラス固有のヒープ・ヒストグラムを取得できます。

jmap -histoコマンドでは、実行中のプロセスのヒープ・ヒストグラムを出力できます。コア・ファイルのヒープ・ヒストグラムを出力するには、jhsdb jmap --histoを使用します。

実行中のプロセスに対してjmap -histoコマンドが実行されると、ツールはクラスごとにオブジェクト数、メモリー・サイズ(バイト)、および完全修飾クラス名を出力します。Java HotSpot VMの内部クラスは山カッコで囲まれます。ヒストグラムは、ヒープがどのように使用されているかを理解するのに役立ちます。オブジェクトのサイズを得るには、合計サイズをそのオブジェクト型の数で割る必要があります。

次の例は、19256というPID番号を持つプロセスに対してjmap -histoコマンドを実行した場合の出力を示しています。

c:\Program Files\Java\jdk-13\bin>jmap -histo 19256
No dump file specified
 num     #instances         #bytes  class name (module)
-------------------------------------------------------
   1:         20913        1658720  [B (java.base@13-ea)
   2:          3647        1516888  [I (java.base@13-ea)
   3:         12321         492840  java.security.AccessControlContext (java.base@13-ea)
   4:         14806         355344  java.lang.String (java.base@13-ea)
   5:          2441         298464  java.lang.Class (java.base@13-ea)
   6:          5169         289464  jdk.internal.org.objectweb.asm.SymbolTable$Entry (java.base@13-ea)
   7:          5896         284216  [Ljava.lang.Object; (java.base@13-ea)
   8:          6887         220384  java.util.HashMap$Node (java.base@13-ea)
   9:           237         194640  [Ljdk.internal.org.objectweb.asm.SymbolTable$Entry; (java.base@13-ea)
  10:          5119         163808  java.util.ArrayList$Itr (java.base@13-ea)
  11:          1922         153760  java.awt.event.MouseEvent (java.desktop@13-ea)
  12:           672         139776  sun.java2d.SunGraphics2D (java.desktop@13-ea)
  13:          4101         131232  java.lang.ref.WeakReference (java.base@13-ea)
  14:           655         101848  [Ljava.util.HashMap$Node; (java.base@13-ea)
  15:          3915          93960  sun.awt.EventQueueItem (java.desktop@13-ea)
  16:           367          89008  [C (java.base@13-ea)
  17:          3708          88992  java.awt.Point (java.desktop@13-ea)
  18:          2158          86320  java.lang.invoke.MethodType (java.base@13-ea)
  19:          3026          81832  [Ljava.lang.Class; (java.base@13-ea)
  20:           348          77952  jdk.internal.org.objectweb.asm.MethodWriter (java.base@13-ea)
  21:          1016          73152  java.awt.geom.AffineTransform (java.desktop@13-ea)
  22:          1017          65088  java.awt.event.InvocationEvent (java.desktop@13-ea)
  23:          2013          64416  java.awt.Rectangle (java.desktop@13-ea)
  24:          1341          64368  java.lang.invoke.MemberName (java.base@13-ea)
  25:          1849          59168  java.util.concurrent.ConcurrentHashMap$Node (java.base@13-ea)
... more lines removed here to reduce output...
1414:             1             16  sun.util.resources.LocaleData$LocaleDataStrategy (java.base@13-ea)
1415:             1             16  sun.util.resources.provider.NonBaseLocaleDataMetaInfo (jdk.localedata@13-ea)
Total        145508        8388608

コア・ファイルに対してjhsdb jmap --histoコマンドが実行されると、ツールはクラスごとにシリアル番号、インスタンス数、バイト数、およびクラス名を出力します。Java HotSpot VMの内部クラスには、先頭にアスタリスク(*)が付けられます。

次の例は、jhsdb jmap --histoコマンドをコア・ファイルに対して実行した場合の出力を示しています。

& jhsdb jmap --exe /usr/java/jdk_12/bin/java --core core.16395 --histo
Attaching to core core.16395 from executable /usr/java/jdk_12/bin/java please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 12-ea+30
Iterating over heap. This may take a while...
Object Histogram:

num     #instances     #bytes   Class description
--------------------------------------------------------------------------
1:           11102     564520   byte[]
2:           10065     241560   java.lang.String
3:            1421     163392   java.lang.Class
4:           26403    2997816   * ConstMethodKlass
5:           26403    2118728   * MethodKlass
6:           39750    1613184   * SymbolKlass
7:            2011    1268896   * ConstantPoolKlass
8:            2011    1097040   * InstanceKlassKlass
9:            1906     882048   * ConstantPoolCacheKlass
10:           1614     125752   java.lang.Object[]
11:           1160      64960   jdk.internal.org.objectweb.asm.Item
12:           1834      58688   java.util.HashMap$Node
13:            359      40880   java.util.HashMap$Node[]
14:           1189      38048   java.util.concurrent.ConcurrentHashMap$Node
15:             46      37280   jdk.internal.org.objectweb.asm.Item[]
16:             29      35600   char[]
17:            968      32320   int[]
18:            650      26000   java.lang.invoke.MethodType
19:            475      22800   java.lang.invoke.MemberName

クラス・ローダーの統計

jmapコマンドを-clstatsオプションとともに使用して、Javaヒープのクラス・ローダー統計を出力します。

jmapコマンドは、プロセスIDを使用して実行中のプロセスに接続し、メタスペースにロードされたクラスに関する詳細情報を出力します。

  • Index - クラスの一意の索引
  • Super - スーパー・クラスの索引番号
  • InstBytes - インスタンスごとのバイト数
  • KlassBytes - クラスのバイト数
  • annotations - 注釈のサイズ
  • CpAll - クラス当たりの定数、タグ、キャッシュおよびオペランドの合計サイズ
  • MethodCount - クラスごとのメソッド数
  • Bytecodes - バイト・コードに使用されるバイト数
  • MethodAll - メソッド、CONSTMETHOD、スタック・マップおよびメソッド・データごとの合計バイト・サイズ
  • ROAll - 読取り専用メモリーに配置できるクラス・メタデータのサイズ
  • RWAll - 読取り/書込みメモリーに配置する必要のあるクラス・メタデータのサイズ
  • Total - ROAllとRWAllの合計
  • ClassName - ロードされたクラスの名前

次の例は、14400というPID番号を持つプロセスに対してjmap -clstatsコマンドを実行した場合の出力のサブセットを示しています。

c:\Program Files\Java\jdk-13\bin>jmap -clstats 11848
Index Super InstBytes KlassBytes annotations   CpAll MethodCount Bytecodes MethodAll   ROAll    RWAll    Total ClassName
    1    -1    313192        512           0       0           0         0         0      24      624      648 [B
    2    51    287648        784           0   23344         147      5815     52456   28960    50248    79208 java.lang.Class
    3    -1    259936        512           0       0           0         0         0      24      624      648 [I
    4    51    171000        680         136   16304         120      4831     48024   22408    44680    67088 java.lang.String
    5    -1    147200        512           0       0           0         0         0      24      624      648 [Ljava.lang.Object;
    6    51    123680        600           0    1384           7       149      1888    1200     3024     4224 java.util.HashMap$Node
    7    51     53440        608           0    1360           9       213      2472    1632     3184     4816 java.util.concurrent.ConcurrentHashMap$Node
    8    -1     51832        512           0       0           0         0         0      24      624      648 [C
    9    -1     49904        512           0       0           0         0         0      32      624      656 [Ljava.util.HashMap$Node;
   10    51     31200        624           0    1512           8       240      2224    1472     3256     4728 java.util.Hashtable$Entry
   11    51     25536        592           0   11520          89      4365     48344   16696    45480    62176 java.lang.invoke.MemberName
   12  1614     19296       1024           0    7904          51      4071     30304   14664    25760    40424 java.util.HashMap
   13    -1     18368        512           0       0           0         0         0      32      624      656 [Ljava.util.concurrent.ConcurrentHashMap$Node;
   14    51     17504        544         120    5464          37      1783     14968    7416    14392    21808 java.lang.invoke.LambdaForm$Name
   15    -1     16680        512           0       0           0         0         0      80      624      704 [Ljava.lang.Class;
...lines removed to reduce output... 2342  1972         0        560           0    1912           7       170      1520    1312     3016     4328 sun.util.logging.internal.LoggingProviderImpl
 2343    51         0        528           0     232           1         0       144     128      936     1064 sun.util.logging.internal.LoggingProviderImpl$LogManagerAccess
              2081120    1635072       10680 5108776       27932   1288637   7813992 5420704 10014136 15434840 Total
                13.5%      10.6%        0.1%   33.1%           -      8.3%     50.6%   35.1%    64.9%   100.0%
Index Super InstBytes KlassBytes annotations   CpAll MethodCount Bytecodes MethodAll   ROAll    RWAll    Total ClassName

jpsユーティリティ

jpsユーティリティは、ターゲット・システム上の現在のユーザーで計測されたすべてのJava HotSpot VMを一覧表示します。

VMが埋め込まれた環境、つまりjava起動ツールではなくJNI呼出しAPIを使用してVMが起動される環境では、このユーティリティが非常に役立ちます。こうした環境では、プロセス・リスト内でJavaプロセスを認識するのが常に容易であるとはかぎりません。

次の例は、jpsユーティリティの使用方法を示しています。

$ jps
16217 MyApplication
16342 jps

jpsユーティリティは、ユーザーがアクセス権を持つ仮想マシンを一覧表示します。この判断には、オペレーティング・システムに固有のアクセス制御メカニズムが使用されます。

このユーティリティには、PIDの一覧表示に加え、アプリケーションのmainメソッドに渡された引数、VM引数の完全なリスト、アプリケーションのmainクラスの完全なパッケージ名を出力するオプションも用意されています。また、リモート・システム上でjstatdデーモンが実行されていれば、jpsユーティリティはリモート・システム上のプロセスを一覧表示することもできます。

jrunscriptユーティリティ

jrunscriptユーティリティはコマンド行スクリプト・シェルです。

インタラクティブ・モード、バッチ・モードの両方のスクリプト実行がサポートされています。このシェルではデフォルトでJavaScriptが使用されますが、他の任意のスクリプト言語を指定することもできます。そのためには、そのスクリプト・エンジンの.classファイルを含むJARファイルへのパスを指定します。

jrunscriptユーティリティは、Java言語とスクリプト言語との通信によって探求的なプログラミング・スタイルをサポートしています。

jstackユーティリティ

jstackユーティリティではなくjcmdまたはjhsdb jstackユーティリティを使用して、JVMおよびJavaアプリケーションの問題を診断します。

JVMおよびJavaアプリケーションの問題を診断するには、JDK Mission Control、フライト・レコーダおよびjcmdユーティリティを使用できます。診断機能を強化し、パフォーマンスのオーバーヘッドを削減するには、以前のjstack,ユーティリティのかわりに最新のユーティリティjcmdの使用をお薦めします。

次の項では、jstackおよびjhsdb jstackユーティリティによるトラブルシューティング手法について説明します。

jstackユーティリティによるトラブルシューティング

jstackコマンド行ユーティリティは、指定されたプロセスに接続し、仮想マシンに接続されたすべてのスレッド(JavaスレッドやVM内部スレッドも含む)のスタック・トレースを出力する以外に、オプションでネイティブ・スタック・フレームも出力します。このユーティリティではデッドロック検出も実行されます。コア・ファイルには、jhsdb jstackを使用します。

すべてのスレッドのスタック・トレースは、デッドロックやハングアップなど、いくつかの問題の診断に役立つ可能性があります。

-lオプションは、所有可能なシンクロナイザをヒープ内で探してjava.util.concurrent.locksに関する情報を出力するように、ユーティリティに指示します。このオプションがない場合、スレッド・ダンプにはモニターの情報のみが含まれます。

jstack pidオプションの出力は、アプリケーション・コンソール(標準入力)で[Ctrl]+[\]を押すか、プロセスにquitシグナルを送信した場合に得られるものと同じです。出力例については、「Ctrl+Breakハンドラ」を参照してください。

スレッド・ダンプは、プログラム内でThread.getAllStackTracesメソッドを使って、またはデバッガ内ですべてのスレッド・スタックを出力するデバッガ・オプション(jdbサンプル・デバッガの場合はwhereコマンド)を使って取得することもできます。

コア・ダンプからのスタック・トレース

コア・ダンプからスタック・トレースを取得するにはjhsdb jstackコマンドを使用します。

コア・ダンプからスタック・トレースを取得するには、次の例のように、コア・ファイルでjhsdb jstackコマンドを実行します。

$ jhsdb jstack --exe java-home/bin/java --core core-file

混合スタック

jhsdb jstackユーティリティは、混合スタックの出力に使用することもできます(つまり、Javaスタックの他にネイティブ・スタック・フレームも出力できます)。ネイティブ・フレームとは、VMコードやJNI/ネイティブ・コードに関連付けられたC/C++フレームのことです。

混合スタックを出力するには、次の例に示すように--mixedオプションを使用します。

>jhsdb jstack --mixed --pid 21177
Attaching to process ID 21177, please wait...Debugger attached successfully.
Server compiler detected.
JVM version is 14-ea+29-1384
Deadlock Detection:

No deadlocks found.

----------------- 0 -----------------
----------------- 1 -----------------
"DestroyJavaVM" #18 prio=5 tid=0x000001df4706f000 nid=0x744 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   JavaThread state: _thread_blocked
0x00007ffa4529f9f4      ntdll!ZwWaitForAlertByThreadId + 0x14
0x000001df2533dc50              ????????
----------------- 2 -----------------
0x00007ffa4529c144      ntdll!NtWaitForSingleObject + 0x14
----------------- 3 -----------------
0x00007ffa4529f9f4      ntdll!ZwWaitForAlertByThreadId + 0x14
----------------- 4 -----------------
0x00007ffa4529c144      ntdll!NtWaitForSingleObject + 0x14
----------------- 5 -----------------
0x00007ffa4529f9f4      ntdll!ZwWaitForAlertByThreadId + 0x14
----------------- 6 -----------------
0x00007ffa4529f9f4      ntdll!ZwWaitForAlertByThreadId + 0x14
----------------- 7 -----------------
0x00007ffa4529f9f4      ntdll!ZwWaitForAlertByThreadId + 0x14
----------------- 8 -----------------
"Reference Handler" #2 daemon prio=10 tid=0x000001df47020000 nid=0x4728 waiting on condition [0x000000a733aff000]
   java.lang.Thread.State: RUNNABLE
   JavaThread state: _thread_blocked
0x00007ffa4529f9f4      ntdll!ZwWaitForAlertByThreadId + 0x14
0x000001df2533e280              ????????
----------------- 9 -----------------
"Finalizer" #3 daemon prio=8 tid=0x000001df4702b000 nid=0x5278 in Object.wait() [0x000000a733bfe000]
   java.lang.Thread.State: WAITING (on object monitor)
   JavaThread state: _thread_blocked
0x00007ffa4529c144      ntdll!NtWaitForSingleObject + 0x14
----------------- 10 -----------------
"Signal Dispatcher" #4 daemon prio=9 tid=0x000001df47053800 nid=0xac0 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   JavaThread state: _thread_blocked
0x00007ffa4529c144      ntdll!NtWaitForSingleObject + 0x14
----------------- 11 -----------------
"Attach Listener" #5 daemon prio=5 tid=0x000001df47058800 nid=0x3980 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   JavaThread state: _thread_blocked
0x00007ffa4529c144      ntdll!NtWaitForSingleObject + 0x14
0x000001df47059390              ????????
----------------- 12 -----------------
"Service Thread" #6 daemon prio=9 tid=0x000001df4705b800 nid=0x3350 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   JavaThread state: _thread_blocked
0x00007ffa4529f9f4      ntdll!ZwWaitForAlertByThreadId + 0x14
----------------- 13 -----------------
"C2 CompilerThread0" #7 daemon prio=9 tid=0x000001df47068800 nid=0x51e8 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   JavaThread state: _thread_blocked
0x00007ffa4529f9f4      ntdll!ZwWaitForAlertByThreadId + 0x14
0x000001df2533d590              ????????
----------------- 14 -----------------
"C1 CompilerThread0" #9 daemon prio=9 tid=0x000001df4705d800 nid=0xc20 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   JavaThread state: _thread_blocked
0x00007ffa4529f9f4      ntdll!ZwWaitForAlertByThreadId + 0x14
0x000001df2533d590              ????????
----------------- 15 -----------------
"Sweeper thread" #10 daemon prio=9 tid=0x000001df4706c000 nid=0x1a64 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   JavaThread state: _thread_blocked
0x00007ffa4529f9f4      ntdll!ZwWaitForAlertByThreadId + 0x14
----------------- 16 -----------------
"Notification Thread" #11 daemon prio=9 tid=0x000001df47070000 nid=0xddc runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   JavaThread state: _thread_blocked
0x00007ffa4529f9f4      ntdll!ZwWaitForAlertByThreadId + 0x14
----------------- 17 -----------------
0x00007ffa4529f9f4      ntdll!ZwWaitForAlertByThreadId + 0x14
0x00000f3e40772a94              ????????
----------------- 18 -----------------
"Common-Cleaner" #12 daemon prio=8 tid=0x000001df4706b000 nid=0x2054 in Object.wait() [0x000000a7344fe000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
   JavaThread state: _thread_blocked
0x00007ffa4529c144      ntdll!NtWaitForSingleObject + 0x14
----------------- 19 -----------------
"Java2D Disposer" #13 daemon prio=10 tid=0x000001df4706c800 nid=0x4770 in Object.wait() [0x000000a7345ff000]
   java.lang.Thread.State: WAITING (on object monitor)
   JavaThread state: _thread_blocked
0x00007ffa4529c144      ntdll!NtWaitForSingleObject + 0x14
----------------- 20 -----------------
"AWT-Shutdown" #14 prio=5 tid=0x000001df4706d800 nid=0x4ed4 in Object.wait() [0x000000a7346fe000]
   java.lang.Thread.State: WAITING (on object monitor)
   JavaThread state: _thread_blocked
0x00007ffa4529c144      ntdll!NtWaitForSingleObject + 0x14
----------------- 21 -----------------
"AWT-Windows" #15 daemon prio=6 tid=0x000001df4706e800 nid=0x15e8 runnable [0x000000a7347ff000]
   java.lang.Thread.State: RUNNABLE
   JavaThread state: _thread_in_native
----------------- 22 -----------------
"AWT-EventQueue-0" #17 prio=6 tid=0x000001df4706a000 nid=0x2f54 waiting on condition [0x000000a7348fe000]
   java.lang.Thread.State: WAITING (parking)
   JavaThread state: _thread_blocked
0x00007ffa4529c144      ntdll!NtWaitForSingleObject + 0x14
----------------- 23 -----------------
----------------- 24 -----------------
----------------- 25 -----------------

先頭にアスタリスク(*)が付いているフレームがJavaフレーム、先頭にアスタリスクが付いていないフレームがネイティブC/C++フレームです。

このユーティリティの出力をc++filtによってパイプで連結すると、C++分解シンボル名を分解解除できます。Java HotSpot VMはC++言語で開発されているため、jhsdb jstackユーティリティはJava HotSpotの内部関数のC++分解シンボル名を出力します。

c++filtユーティリティは、Linux上のネイティブC++コンパイラ・スイートであるgnuとともに配布されます。

jstatユーティリティ

jstatユーティリティは、Java HotSpot VMの組込みインストゥルメンテーションを使用して、実行中アプリケーションのパフォーマンスやリソース消費に関する情報を提供します。

このツールは、パフォーマンスの問題、特にヒープ・サイズ決定やガベージ・コレクションに関係する問題を診断するときに使用できます。jstatユーティリティでは、特殊なオプション付きでVMを起動する必要はありません。Java HotSpot VMの組込みインストゥルメンテーションはデフォルトで有効になります。このユーティリティは、Oracleがサポートしているすべてのオペレーティング・システム・プラットフォームのJDKダウンロードに含まれています。

ノート:

FAT32ファイル・システム上では、インストゥルメンテーションにアクセスできません。

Java Development Kitツール仕様jstatコマンドに関する項を参照してください。

jstatユーティリティは、仮想マシン識別子(VMID)を使用してターゲット・プロセスを識別します。ドキュメントにはVMIDの構文が記載されていますが、それに必要な唯一のコンポーネントはローカル仮想マシン識別子(LVMID)です。LVMIDは、(必ずではありませんが、)一般的にはターゲットJVMプロセスに対するオペレーティング・システムのPIDです。

jstatユーティリティで提供されるデータは、Linuxオペレーティング・システムのvmstatおよびiostatで提供されるデータに似ています。

データをグラフィカルに表現する場合は、visualgcツールを使用できます。「visualgcツール」を参照してください。

-gcutilオプションの使用例を次に示します。この例では、jstatユーティリティがLVMID番号2834に接続し、250ミリ秒間隔で7つのサンプルを取っています。

$ jstat -gcutil 2834 250 7
  S0     S1     E      O      M     YGC     YGCT    FGC    FGCT     GCT   
  0.00  99.74  13.49   7.86  95.82      3    0.124     0    0.000    0.124
  0.00  99.74  13.49   7.86  95.82      3    0.124     0    0.000    0.124
  0.00  99.74  13.49   7.86  95.82      3    0.124     0    0.000    0.124
  0.00  99.74  13.49   7.86  95.82      3    0.124     0    0.000    0.124
  0.00  99.74  13.49   7.86  95.82      3    0.124     0    0.000    0.124
  0.00  99.74  13.49   7.86  95.82      3    0.124     0    0.000    0.124
  0.00  99.74  13.49   7.86  95.82      3    0.124     0    0.000    0.124

この例の出力は、若い世代のコレクションが3番目と4番目のサンプル間で行われたことを示しています。コレクションには0.017秒かかっており、オブジェクトがeden領域(E)からOld領域(O)に昇格したため、old領域の使用率は46.56%から54.60%に増加しています。

-gcnewオプションの使用例を次に示します。この例では、jstatユーティリティがLVMID番号2834に接続し、250ミリ秒間隔でサンプルを取り、出力を表示しています。さらに、-h3オプションを使用して、データが3行表示されるごとに列ヘッダーを表示します。

$ jstat -gcnew -h3 2834 250
S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT  
 192.0  192.0    0.0    0.0 15  15   96.0   1984.0    942.0    218    1.999
 192.0  192.0    0.0    0.0 15  15   96.0   1984.0   1024.8    218    1.999
 192.0  192.0    0.0    0.0 15  15   96.0   1984.0   1068.1    218    1.999
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT  
 192.0  192.0    0.0    0.0 15  15   96.0   1984.0   1109.0    218    1.999
 192.0  192.0    0.0  103.2  1  15   96.0   1984.0      0.0    219    2.019
 192.0  192.0    0.0  103.2  1  15   96.0   1984.0     71.6    219    2.019
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT  
 192.0  192.0    0.0  103.2  1  15   96.0   1984.0     73.7    219    2.019
 192.0  192.0    0.0  103.2  1  15   96.0   1984.0     78.0    219    2.019
 192.0  192.0    0.0  103.2  1  15   96.0   1984.0    116.1    219    2.019

この例では、ヘッダー文字列の繰返しが見られるほかにも、4番目と5番目のサンプル間で若い世代のコレクションが発生し、その継続時間が0.02秒だったことがわかります。このコレクションでは、Survivor領域1の使用率(S1U)が適切なSurvivorサイズ(DSS)を超過するのに十分なライブ・データが検出されました。この結果、オブジェクトは、Old世代(この出力には非表示)へ昇格され、殿堂入りしきい値(TT)が、15から1へ降格されました。

-gcoldcapacityオプションの使用例を次に示します。この例では、jstatユーティリティがLVMID番号21891に接続し、250ミリ秒間隔で3つのサンプルを取っています。-tオプションを使用して、最初の列にサンプルごとのタイムスタンプを表示しています。

$ jstat -gcoldcapacity -t 21891 250 3
Timestamp    OGCMN     OGCMX       OGC        OC   YGC   FGC     FGCT     GCT
    150.1   1408.0   60544.0   11696.0   11696.0   194    80    2.874   3.799
    150.4   1408.0   60544.0   13820.0   13820.0   194    81    2.938   3.863
    150.7   1408.0   60544.0   13820.0   13820.0   194    81    2.938   3.863

Timestamp列には、ターゲットJVMの起動時からの経過時間が、秒単位で報告されています。さらに、-gcoldcapacity出力では、割当て要求または昇格要求あるいはその両方を満たすためにヒープが拡張するたびに、Old世代の容量(OGC)とOld領域の容量(OC)とが増加していることがわかります。OGCは、81番目の全世代の容量(FGC)後に、11696 KBから13820 KBへ増加しています。この世代(および領域)の最大容量は、60544 Kバイト(OGCMX)なので、まだ拡張できる余裕が残されています。

visualgcツール

visualgcツールは、ガベージ・コレクション(GC)システムのグラフィカル表示を提供します。

visualgcツールは、jstatツールに関連があります。「jstatユーティリティ」を参照してください。visualgcツールは、ガベージ・コレクション(GC)システムのグラフィカル表示を提供します。これはjstatと同様に、Java HotSpot VMの組込みインストゥルメンテーションを使用します。

visualgcツールはJDKリリースには含まれていませんが、jvmstatテクノロジ・ページから個別のダウンロードとして入手できます。

図2-2は、GCおよびヒープの視覚化を示しています。

図2-2 visualgcからのサンプル出力

図2-2の説明が続きます
「図2-2 visualgcからのサンプル出力」の説明

Ctrl+Breakハンドラ

Linuxオペレーティング・システムの場合、アプリケーション・コンソール(標準入力)で[Ctrl]キーとバックスラッシュ([\])キーの組合せを押すと、Java HotSpot VMからアプリケーションの標準出力にスレッド・ダンプが出力されます。Windowsの場合、同等のキー・シーケンスは[Ctrl]キーと[Break]キーです。これらのキーの組合せを表す一般的な用語は、Ctrl+Breakハンドラです。

Linuxオペレーティング・システムでは、Javaプロセスがquitシグナルを受信するとスレッド・ダンプが出力されます。したがって、kill -QUIT pidコマンドを実行すると、pidをIDに持つプロセスから標準出力にスレッド・ダンプが出力されます。

次の項では、Ctrl+Breakハンドラによってトレースされるデータについて説明します。

スレッド・ダンプ

スレッド・ダンプは、仮想マシン内のすべてのJavaスレッドのスレッド・スタック(スレッドの状態など)で構成されています。

スレッド・ダンプによってアプリケーションが終了することはなく、スレッド情報が出力された後もアプリケーションは続行します。

次の例はスレッド・ダンプを示しています。

Full thread dump Java HotSpot(TM) Client VM (1.6.0-rc-b100 mixed mode):

"DestroyJavaVM" prio=10 tid=0x00030400 nid=0x2 waiting on condition [0x00000000..0xfe77fbf0]
   java.lang.Thread.State: RUNNABLE

"Thread2" prio=10 tid=0x000d7c00 nid=0xb waiting for monitor entry [0xf36ff000..0xf36ff8c0]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at Deadlock$DeadlockMakerThread.run(Deadlock.java:32)
        - waiting to lock <0xf819a938> (a java.lang.String)
        - locked <0xf819a970> (a java.lang.String)

"Thread1" prio=10 tid=0x000d6c00 nid=0xa waiting for monitor entry [0xf37ff000..0xf37ffbc0]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at Deadlock$DeadlockMakerThread.run(Deadlock.java:32)
        - waiting to lock <0xf819a970> (a java.lang.String)
        - locked <0xf819a938> (a java.lang.String)

"Low Memory Detector" daemon prio=10 tid=0x000c7800 nid=0x8 runnable [0x00000000..0x00000000]
   java.lang.Thread.State: RUNNABLE

"CompilerThread0" daemon prio=10 tid=0x000c5400 nid=0x7 waiting on condition [0x00000000..0x00000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" daemon prio=10 tid=0x000c4400 nid=0x6 waiting on condition [0x00000000..0x00000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" daemon prio=10 tid=0x000b2800 nid=0x5 in Object.wait() [0xf3f7f000..0xf3f7f9c0]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0xf4000b40> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116)
        - locked <0xf4000b40> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

"Reference Handler" daemon prio=10 tid=0x000ae000 nid=0x4 in Object.wait() [0xfe57f000..0xfe57f940]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0xf4000a40> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:485)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
        - locked <0xf4000a40> (a java.lang.ref.Reference$Lock)

"VM Thread" prio=10 tid=0x000ab000 nid=0x3 runnable 

"VM Periodic Task Thread" prio=10 tid=0x000c8c00 nid=0x9 waiting on condition 

この出力は、空白行で区切られたいくつかのスレッド・エントリで構成されます。Javaスレッド(Java言語コードを実行できるスレッド)がまず出力され、それらの後にVM内部スレッドに関する情報が続きます。各スレッド・エントリは、ヘッダー行とその後に続くスレッド・スタック・トレースで構成されます。

ヘッダー行には、スレッドに関する次の情報が含まれます。

  • スレッド名

  • スレッドがデーモン・スレッドかどうかのマーク

  • スレッド優先度(prio)

  • スレッドID (tid)。メモリー内のスレッド構造体のアドレスです

  • ネイティブ・スレッドのID (nid)

  • スレッド・ダンプ時にスレッドが実行していた内容を示す、スレッド状態詳細は、表2-2を参照してください。

  • アドレス範囲(スレッドのおおよその有効なスタック領域を表す)

スレッド・ダンプのスレッド状態

スレッド・ダンプに表示される可能性があるスレッド状態のリスト。

表2-2は、Ctrl+Breakハンドラによるスレッド・ダンプで可能なスレッド状態を示しています。

表2-2 スレッド・ダンプのスレッド状態

スレッド状態 説明

NEW

スレッドはまだ開始されていません。

RUNNABLE

スレッドはJVM内で実行されています。

BLOCKED

スレッドはモニター・ロックを待機してブロックされています。

WAITING

スレッドは、別のスレッドが特定のアクションを実行するのを無期限に待機しています。

TIMED_WAITING

スレッドは指定された待機時間、別のスレッドがアクションを実行するのを待機しています。

TERMINATED

スレッドは終了しています。

デッドロックの検出

Ctrl+Breakハンドラは、スレッドのデッドロック検出にも使用できます。

Ctrl+Breakハンドラは、スレッド・スタックだけでなく、デッドロック検出アルゴリズムも実行します。デッドロックが検出された場合、次の例に示すように、Ctrl+Breakハンドラは、デッドロックされた各スレッドに関するスレッド・ダンプの後に追加情報を出力します。

Found one Java-level deadlock:
=============================
"Thread2":
  waiting to lock monitor 0x000af330 (object 0xf819a938, a java.lang.String),
  which is held by "Thread1"
"Thread1":
  waiting to lock monitor 0x000af398 (object 0xf819a970, a java.lang.String),
  which is held by "Thread2"

Java stack information for the threads listed above:
===================================================
"Thread2":
        at Deadlock$DeadlockMakerThread.run(Deadlock.java:32)
        - waiting to lock <0xf819a938> (a java.lang.String)
        - locked <0xf819a970> (a java.lang.String)
"Thread1":
        at Deadlock$DeadlockMakerThread.run(Deadlock.java:32)
        - waiting to lock <0xf819a970> (a java.lang.String)
        - locked <0xf819a938> (a java.lang.String)

Found 1 deadlock.

JVMフラグ-XX:+PrintConcurrentLocksが設定されている場合、Ctrl+Breakハンドラは各スレッドが所有している並行ロックのリストも出力します。

ヒープ・サマリー

Ctrl+Breakハンドラはヒープ・サマリーの出力にも使用できます。

次の例では、様々な世代(ヒープ領域)がそのサイズ、使用量、アドレス範囲とともに示されています。アドレス範囲は特に、pmapなどのツールでプロセスを調査する場合にも役立ちます。

Heap
 def new generation   total 1152K, used 435K [0x22960000, 0x22a90000, 0x22e40000
)
  eden space 1088K,  40% used [0x22960000, 0x229ccd40, 0x22a70000)
  from space 64K,   0% used [0x22a70000, 0x22a70000, 0x22a80000)
  to   space 64K,   0% used [0x22a80000, 0x22a80000, 0x22a90000)
 tenured generation   total 13728K, used 6971K [0x22e40000, 0x23ba8000, 0x269600
00)
   the space 13728K,  50% used [0x22e40000, 0x2350ecb0, 0x2350ee00, 0x23ba8000)
 compacting perm gen  total 12288K, used 1417K [0x26960000, 0x27560000, 0x2a9600
00)
   the space 12288K,  11% used [0x26960000, 0x26ac24f8, 0x26ac2600, 0x27560000)
    ro space 8192K,  62% used [0x2a960000, 0x2ae5ba98, 0x2ae5bc00, 0x2b160000)
    rw space 12288K,  52% used [0x2b160000, 0x2b79e410, 0x2b79e600, 0x2bd60000)

JVMフラグ-XX:+PrintClassHistogramが設定されている場合、Ctrl+Breakハンドラはヒープ・ヒストグラムを生成します。

オペレーティング・システムのネイティブ・ツール

WindowsおよびLinuxオペレーティング・システムは、トラブルシューティングまたは監視に役立つネイティブ・ツールを提供します。

各ツールについて簡単な説明が提供されます。詳細は、オペレーティング・システムのマニュアルまたはLinuxオペレーティング・システムのマニュアル・ページを参照してください。

コマンド行ユーティリティからのログ・ファイルや出力の形式は、リリースごとに異なります。たとえば、致命的エラー・ログの形式に依存するスクリプトを開発した場合、そのログ・ファイルの形式が将来のリリースで変更されれば、同じスクリプトでも動作しなくなる可能性があります。

Windows固有のデバッグ・サポートは、MSDN Developer Networkで検索することもできます。

次の項では、いくつかのオペレーティング・システム・ツールのトラブルシューティング手法および改善について説明します。

オペレーティング・システムに基づくトラブルシューティング・ツール

問題のトラブルシューティングに利用できるWindowsのネイティブ・ツールのリスト。

表2-3は、Windowsオペレーティング・システムで使用可能なトラブルシューティング・ツールの一覧を示しています。

表2-3 Windowsのネイティブ・トラブルシューティング・ツール

ツール 説明

dumpchk

メモリー・ダンプ・ファイルが正常に作成されたことを確認するコマンド行ユーティリティ。このツールは、MicrosoftのWebサイトから入手可能なDebugging Tools for Windowsダウンロードに含まれています。「Windowsでのクラッシュ・ダンプの収集」を参照してください。

msdevデバッガ

Visual C++およびWin32デバッガの起動に使用可能なコマンド行ユーティリティ。

userdump

User Mode Process Dumperは、MicrosoftのWebサイトから入手可能なOEM Support Toolsダウンロードに含まれています。「Windowsでのクラッシュ・ダンプの収集」を参照してください。

windbg

Windowsデバッガは、Windowsアプリケーションまたはクラッシュ・ダンプのデバッグに使用できます。このツールは、MicrosoftのWebサイトから入手可能なDebugging Tools for Windowsダウンロードに含まれています。「Windowsでのクラッシュ・ダンプの収集」を参照してください。

/Mdおよび/Mddコンパイラ・オプション

メモリー割当てを追跡するための追加サポートを自動的に含めるコンパイラ・オプション。

表2-4では、Linuxオペレーティング・システム・バージョン10で導入または改善されたいくつかのトラブルシューティング・ツールについて説明しています。

表2-4 Linuxのネイティブ・トラブルシューティング・ツール

ツール 説明

c++filt

C++分解シンボル名を分解解除します。このユーティリティは、Linux上のgccというネイティブC++コンパイラ・スイートとともに配布されます。

gdb

GNUデバッガ

libnjamd

メモリー割当ての追跡

lsstack

スレッド・スタックの出力

すべてのディストリビューションがデフォルトでこのツールを提供しているわけではありません。したがって、SourceForgeからのダウンロードが必要になる場合があります。

ltrace

ライブラリ呼出しトレーサ

すべてのディストリビューションがデフォルトでこのツールを提供しているわけではありません。したがって、SourceForgeからのダウンロードが必要になる場合があります。

mtraceおよびmuntrace

GNU mallocトレーサ

/procファイルシステム

プロセスや他のシステム情報に関する情報が含まれている仮想ファイルシステム

strace

システム呼出しトレーサ

top

CPU負荷が非常に高いプロセスを表示します。

vmstat

プロセス、メモリー、ページング、ブロックI/O、トラップ、およびCPUアクティビティに関する情報を報告します。

Java HotSpot VMのプローブ・プロバイダ

Java HotSpot VMにはhotspotおよびhotspot_jniという2つの組込みプローブ・プロバイダが含まれるようになりました。

これらのプロバイダは、VMの内部状態やアクティビティだけでなく、実行中のJavaアプリケーションもモニターするために使用できるプローブを配布します。

JVMプローブ・プロバイダは次のように分類できます。

  • VMのライフ・サイクル: VMの初期化の開始と終了、およびVMのシャットダウン

  • スレッドのライフ・サイクル: スレッドの開始と停止、スレッド名、スレッドIDなど

  • クラスのロード: Javaクラスのロードとアンロード

  • ガベージ・コレクション: ガベージ・コレクションの開始と停止、システム全体またはメモリー・プール別

  • メソッドのコンパイル: メソッドのコンパイルの開始と終了、メソッドのロードとアンロード

  • モニター・プローブ: 待機イベント、通知イベント、競合するモニターへの出入り

  • アプリケーションの追跡: メソッドに入る、メソッドから戻る、Javaオブジェクトの割当て

ネイティブ・コードからJavaコードへの呼出しの場合、ネイティブ・コードはJNIインタフェース経由で呼出しを行う必要があります。hotspot_jniプロバイダは、Javaコードを呼び出したりVMの状態を検査したりするためにJNIインタフェースに用意されているメソッドごとに、入口と出口におけるDTraceプローブを管理します。

プローブ・ポイントで現在のスレッドのスタック・トレースを出力するには、ustack組込み関数を使用できます。この関数は、C/C++ネイティブ関数の名前だけでなく、Javaメソッドの名前も出力します。次の例は、あるスレッドがreadシステム・コールを呼び出したときに必ず完全なスタック・トレースを出力する単純なDスクリプトです。

#!/usr/sbin/dtrace -s
syscall::read:entry 
/pid == $1 && tid == 1/ {    
   ustack(50, 0x2000);
}

前の例のスクリプトはread.dというファイルに格納され、次の例に示すように、トレース対象のJavaプロセスのPIDを指定することで実行されます。

read.d pid

Javaアプリケーションで多数のI/Oが生成されたり、なんらかの予期しない遅延が発生したりした場合、DTraceツールやそのustack()アクションを使用すれば、問題を診断しやすくなる可能性があります。

カスタム診断ツール

JDKには、Java Runtime Environmentに配備されているアプリケーションの問題を観察、モニター、プロファイル、デバッグ、および診断するカスタム・ツールを開発するための広範なAPIが含まれています。

新しいツールの開発はこのドキュメントの対象外です。かわりにこのセクションでは、使用可能なAPIの概要を簡単に説明します。

この項に示されたすべてのパッケージは、Java SE API仕様で説明されています。

JDKダウンロードに含まれるコード例やデモ・コードを参照してください。

次の項では、トラブルシューティングのためのカスタム診断ツールとして使用できるパッケージ、インタフェース・クラスおよびJavaデバッガについて説明します。

java.lang.managementパッケージ

java.lang.managementパッケージは、JVMやオペレーティング・システムをモニターおよび管理するための管理インタフェースを提供します。

具体的には、次の各システムのインタフェースがカバーされています。

  • クラスのロード

  • コンパイル

  • ガベージ・コレクション

  • メモリー・マネージャ

  • ランタイム

  • スレッド

JDKリリースにはjava.lang.managementパッケージのほかに、プラットフォーム拡張がcom.sun.managementパッケージとして含まれています。プラットフォーム拡張には、コレクションをサイクルで実行するガベージ・コレクタから詳細統計を取得するための管理インタフェースが含まれています。これらの拡張には、オペレーティング・システムから追加のメモリー統計を取得するための管理インタフェースも含まれています。

java.lang.instrumentパッケージ

java.lang.instrumentパッケージは、Javaプログラミング言語エージェントがJVMで実行中のプログラムを計測することを許可するサービスを提供します。

インストゥルメンテーションは、プロファイラなどのツールや、メソッド呼出しをトレースするためのツールなどで使用されます。このパッケージを使えば、ロード時および動的計測の両方が容易になります。また、ロード済クラスに関する情報や特定のオブジェクトが消費するストレージ量に関する情報を取得するメソッドも含まれています。

java.lang.Threadクラス

java.lang.Threadクラスには、すべてのライブ・メソッドのスタック・トレースのマップを返す、getAllStackTracesと呼ばれるstaticメソッドが含まれています。

Threadクラスには、スレッドの状態を返す、getStateと呼ばれるメソッドも含まれています。スレッドの状態はjava.lang.Thread.State列挙型で定義されます。これらのメソッドは、診断またはモニタリング機能をアプリケーションに追加する際に役立つことがあります。

JVM Tool Interface

JVM Tools Interface (JVM TI)とは、様々な開発ツールやモニタリング・ツールで使用できるネイティブ(C/C++)プログラミング・インタフェースです。

JVM TIは、VMの状態にアクセスする必要のある各種ツール(プロファイリング・ツール、デバッグ・ツール、モニタリング・ツール、スレッド分析ツール、カバレッジ分析ツールを含むがこれに限らない)のためのインタフェースを提供します。

JVM TIに依存するエージェントのいくつかの例を次に示します。

  • Java Debug Wire Protocol (JDWP)

  • java.lang.instrumentパッケージ

JVM TIの仕様は、JVM Tool Interfaceのドキュメントで参照できます。

Java Platform Debugger Architecture

Java Platform Debugger Architecture (JPDA)は、デバッガやデバッガに似たツールが使用するために設計されたアーキテクチャです。

Java Platform Debugger Architectureは、2つのプログラミング・インタフェースおよびワイヤ・プロトコルで構成されています。

  • Java Virtual Machine Tool Interface (JVM TI)は、仮想マシンへのインタフェースです。「JVM Tool Interface」を参照してください。

  • Java Debug Interface (JDI)は、ユーザー・コード・レベルでの情報および要求を定義します。これは、Javaプログラミング言語アプリケーションをデバッグするためのPure Javaプログラミング言語インタフェースです。JPDAでは、JDIは、デバッガのプロセスから見たデバッグ対象プロセスの仮想マシンのリモート・ビューです。これはフロント・エンドによって実装されます。デバッガに似たアプリケーション(IDE、デバッガ、トレーサ、モニタリング・ツールなど)はクライアントとなります。モジュールjdk.jdiを参照してください。

  • Java Debug Wire Protocol (JDWP)は、デバッグされるプロセスと、JDIを実装したデバッガ・フロント・エンドとの間で転送される、情報および要求の形式を定義します。

jdbユーティリティは、コマンド行デバッガの例としてJDKに含まれています。jdbユーティリティは、JDIを使ってターゲットVMを起動または接続します。「jdbユーティリティ」を参照してください。

JDIを使用すれば、従来のデバッガ・タイプのツールだけでなく、ポストモーテム診断の際や、ツールが非協力的なプロセス(ハングアップ・プロセスなど)に接続する必要があるシナリオで役に立つツールを開発することもできます。

ポストモーテム診断ツール

アプリケーションとJava HotSpot VMとの間で発生する問題のポストモーテム診断用に使用可能なツールとオプションのリスト。

表2-5に、ポストモーテム診断用に設計されたオプションおよびツールの要約を示します。アプリケーションがクラッシュした場合、これらのオプションやツールを使用して、クラッシュ発生時、または後でクラッシュ・ダンプからの情報を使用して追加情報を取得できます。

表2-5 ポストモーテム診断ツール

ツールまたはオプション 説明および使用方法

致命的エラー・ログ

回復不能(致命的)なエラーが発生すると、エラー・ログが作成されます。このファイルには、致命的エラーの発生時に取得された情報が含まれています。これは多くの場合、クラッシュ発生時に最初に調べる必要がある項目です。「致命的エラー・ログ」を参照してください。

-XX:+HeapDumpOnOutOfMemoryErrorオプション

このコマンド行オプションは、VMでネイティブのメモリー不足エラーが検出された際にヒープ・ダンプを生成することを指定します。「-XX:HeapDumpOnOutOfMemoryErrorオプション」を参照してください。

-XX:OnErrorオプション

このコマンド行オプションは、致命的エラーの発生時にユーザー指定の一連のスクリプトまたはコマンドを実行することを指定します。たとえばWindowsの場合、このオプションでクラッシュ・ダンプを強制するコマンドを実行できます。ポストモーテム・デバッガが構成されていないシステムでは、このオプションが非常に役立ちます。「-XX:OnErrorオプション」を参照してください。

-XX:+ShowMessageBoxOnErrorオプション

このコマンド行オプションは、致命的エラーの発生時にプロセスを中断します。このオプションはユーザーの応答に応じて、ネイティブ・デバッガ(dbxgdbmsdev)を起動してVMに接続できます。「-XX:ShowMessageBoxOnErrorオプション」を参照してください。

その他の-XXオプション

トラブルシューティングに役立つ-XXコマンド行オプションは、ほかにもいくつかあります。「その他の-XX Optionsオプション」を参照してください。

jhsdb jinfoユーティリティ

このユーティリティは、クラッシュから取得されたコア・ファイル、またはgcoreユーティリティを使用して取得されたコア・ファイルから、構成情報を取得できます。「jinfoユーティリティ」を参照してください。

jhsdb jmapユーティリティ

このユーティリティは、クラッシュから取得されたコア・ファイルから、またはgcoreユーティリティを使用して取得されたコア・ファイルから、ヒープ・ヒストグラムなどのメモリー・マップ情報を取得できます。「jmapユーティリティ」を参照してください。

jstackユーティリティ

このユーティリティは、JavaプロセスからJavaおよびネイティブ・スタックの情報を取得できます。Linuxオペレーティング・システムでは、ユーティリティはコア・ファイルまたはリモート・デバッグ・サーバーからも情報を取得できます。「jstackユーティリティ」を参照してください。

ネイティブ・ツール

各オペレーティング・システムには、ポストモーテム診断に使用可能なネイティブ・ツールおよびユーティリティがあります。「オペレーティング・システムのネイティブ・ツール」を参照してください。

ハングアップ・プロセス・ツール

ハングアップ・プロセスでアプリケーションとJava HotSpot VMとの間で発生する問題を診断するためのツールとオプションは、JDKおよびオペレーティング・システムで使用できます。

表2-6では、ハングアップまたはデッドロックしたプロセスに関連するシナリオで役立つ可能性のあるオプションやツールをまとめています。これらのツールでは、アプリケーション起動時に特殊なオプションは必要ありません。

JVMおよびJavaアプリケーションの問題を診断するには、JDK Mission Control、フライト・レコーダおよびjcmdユーティリティを使用できます。診断機能を強化し、パフォーマンスのオーバーヘッドを削減するには、以前のjstack,、jinfoおよびjmapユーティリティのかわりに最新の診断ツールjcmdの使用をお薦めします。

表2-6 ハングアップ・プロセス・ツール

ツールまたはオプション 説明および使用方法

Ctrl+Breakハンドラ

(Linuxオペレーティング・システムでは[Ctrl]+[\]またはkill -QUIT pid、Windowsでは[Ctrl]+[Break])

このキーの組合せでは、スレッド・ダンプとデッドロック検出が実行されます。Ctrl+Breakハンドラではオプションで、並行ロックとその所有者の一覧や、ヒープ・ヒストグラムを出力することもできます。「Ctrl+Breakハンドラ」を参照してください。

jcmdユーティリティ

このユーティリティを使用してJVMに診断コマンド要求を送信し、JVMではこれらの要求を使用してフライト・レコーダからの記録を制御します。記録はフライト記録のイベントのトラブルシューティングと診断に使用します。「jcmdユーティリティ」を参照してください。

jdbユーティリティ

デバッガ・サポートには、jdbなどのJava言語デバッガがプロセスに接続することを許可する、接続コネクタが含まれています。これは、ハング・アップやデッドロックの発生時に各スレッドが何をしていたのかを示すのに役立つ可能性があります。「jdbユーティリティ」を参照してください。

jinfoユーティリティ

このユーティリティはJavaプロセスから構成情報を取得できます。「jinfoユーティリティ」を参照してください。

jmapユーティリティ

このユーティリティは、Javaプロセスからヒープ・ヒストグラムなどのメモリー・マップ情報を取得できます。jhsdb jmapユーティリティは、プロセスがハングした場合に使用できます。「jmapユーティリティ」を参照してください。

jstackユーティリティ

このユーティリティは、JavaプロセスからJavaおよびネイティブ・スタックの情報を取得できます。「jstackユーティリティ」を参照してください。

ネイティブ・ツール

各オペレーティング・システムには、ハング・アップやデッドロックの状況で役立つ可能性のあるネイティブ・ツールおよびユーティリティがあります。「オペレーティング・システムのネイティブ・ツール」を参照してください。

モニタリング・ツール

アプリケーションの実行を監視し、問題を検出するためのツールとオプションは、JDKおよびオペレーティング・システムで使用できます。

表2-7に示すツールは、実行中のアプリケーションのモニター用に設計されています。

JVMおよびJavaアプリケーションの問題を診断するには、JDK Mission Control、フライト・レコーダおよびjcmdユーティリティを使用できます。診断機能を強化し、パフォーマンスのオーバーヘッドを削減するには、以前のjstack,、jinfoおよびjmapユーティリティのかわりに最新の診断ツールjcmdの使用をお薦めします。

表2-7 モニタリング・ツール

ツールまたはオプション 説明および使用方法

JDK Mission Control

JDK Mission Control (JMC)は、HotSpot JVM用のJDKプロファイリングおよび診断ツール・プラットフォームです。基本的なモニタリングと管理、および本番稼働時のプロファイリングと診断を行う高性能なツール・スイートです。JMCは、プロファイリング・ツールにつきもののパフォーマンス・オーバーヘッドの問題を最小限に抑えます。

jcmdユーティリティ

このユーティリティを使用してJVMに診断コマンド要求を送信し、JVMではこれらの要求を使用してフライト・レコーダからの記録を制御します。記録は、フライト記録のイベントを使用してJVMおよびJavaアプリケーションのトラブルシューティングと診断を行うために使用されます。「jcmdユーティリティ」を参照してください。

JConsoleユーティリティ

このユーティリティは、Java Management Extensions (JMX)に基づくモニタリング・ツールです。このツールは、Java仮想マシンの組込みJMXインストゥルメンテーションを使用して、実行中のアプリケーションのパフォーマンスやリソース消費に関する情報を提供します。「JConsole」を参照してください。

jmapユーティリティ

このユーティリティは、Javaプロセスまたはコア・ファイルからヒープ・ヒストグラムなどのメモリー・マップ情報を取得できます。「jmapユーティリティ」を参照してください。

jpsユーティリティ

このユーティリティは、ターゲット・システム上で計測されたJava HotSpot VMを一覧表示します。VMが埋め込まれた環境、つまりjava起動ツールではなくJNI呼び出しAPIを使ってVMが起動される環境では、このユーティリティが非常に役立ちます。「jpsユーティリティ」を参照してください。

jstackユーティリティ

このユーティリティは、Javaプロセスまたはコア・ファイルからJavaおよびネイティブ・スタックの情報を取得できます。「jstackユーティリティ」を参照してください。

jstatユーティリティ

このユーティリティは、Javaの組込みインストゥルメンテーションを使用して、実行中アプリケーションのパフォーマンスやリソース消費に関する情報を提供します。このツールは、パフォーマンスの問題、特にヒープ・サイズ決定やガベージ・コレクションに関係する問題を診断するときに使用できます。「jstatユーティリティ」を参照してください。

jstatdデーモン

このユーティリティは、計測されたJava仮想マシンの作成と終了をモニターし、ローカル・ホスト上で実行されているVMにリモート・モニタリング・ツールが接続することを許可するインタフェースを提供する、Remote Method Invocation (RMI)サーバー・アプリケーションです。「jstatdデーモン」を参照してください。

visualgcユーティリティ

このユーティリティは、ガベージ・コレクション・システムのグラフィカル表示を提供します。これはjstatと同様に、Java HotSpot VMの組込みインストゥルメンテーションを使用します。「visualgcツール」を参照してください。

ネイティブ・ツール

各オペレーティング・システムには、モニタリング目的に役立つ可能性のあるネイティブ・ツールおよびユーティリティがあります。「オペレーティング・システムのネイティブ・ツール」を参照してください。

その他のツール、オプション、変数、およびプロパティ

問題の診断に役立つ一般的なトラブルシューティングのツール、オプション、変数およびプロパティは、JDKおよびオペレーティング・システムで使用可能です。

特定タイプの問題向けに設計されたツールに加え、表2-8に示すツール、オプション、変数、およびプロパティは、その他の問題を診断するのに役立ちます。

JVMおよびJavaアプリケーションに関する問題を診断するには、JDK Mission Control、フライト・レコーダおよびjcmdユーティリティを使用できます。診断機能を強化し、パフォーマンスのオーバーヘッドを削減するには、以前のjstack,、jinfoおよびjmapユーティリティのかわりに最新の診断ツールjcmdの使用をお薦めします。

表2-8 一般的なトラブルシューティング・ツールおよびオプション

ツールまたはオプション 説明および使用方法

JDK Mission Control

JDK Mission Control (JMC)は、HotSpot JVM用のJDKプロファイリングおよび診断ツール・プラットフォームです。基本的なモニタリングと管理、および本番稼働時のプロファイリングと診断を行う高性能なツール・スイートです。JMCは、プロファイリング・ツールにつきもののパフォーマンス・オーバーヘッドの問題を最小限に抑えます。

jcmdユーティリティ

このユーティリティを使用してJVMに診断コマンド要求を送信し、JVMではこれらの要求を使用してフライト・レコーダからの記録を制御します。記録は、フライト記録のイベントを使用してJVMおよびJavaアプリケーションのトラブルシューティングと診断を行うために使用されます。

jinfoユーティリティ

このユーティリティは、指定されたJavaプロセスの特定のJVMフラグの値を動的に設定、設定解除および変更できます。Linuxオペレーティング・システムでは、構成情報も出力できます。

jrunscriptユーティリティ

このユーティリティはコマンド行スクリプト・シェルで、インタラクティブおよびバッチ・モードの両方のスクリプト実行をサポートしています。

-Xcheck:jniオプション

このオプションは、Java Native Interface (JNI)を使用する、またはサード・パーティのライブラリ(一部のJDBCドライバなど)を採用するアプリケーションの問題を診断する際に役立ちます。「-Xcheck:jniオプション」を参照してください。

-verbose:classオプション

このオプションは、クラスのロードとアンロードのロギングを有効にします。「-verbose:classオプション」を参照してください。

-verbose:gcオプション

このオプションは、ガベージ・コレクション情報のロギングを有効にします。「-verbose:gcオプション」を参照してください。

-verbose:jniオプション

このオプションは、JNIのロギングを有効にします。「-verbose:jniオプション」を参照してください。

JAVA_TOOL_OPTIONS環境変数

この環境変数では、ツールの初期化(具体的には-agentlibまたは-javaagentオプションを使用したネイティブまたはJavaプログラミング言語エージェントの起動)を指定できます。「環境変数とシステム・プロパティ」を参照してください。

java.security.debugシステム・プロパティ

このシステム・プロパティは、Java Runtime Environmentのセキュリティ・チェックが、実行中にトレース・メッセージを出力するかどうかを制御します。「java.security.debugシステム・プロパティ」を参照してください。

jstatdデーモン

jstatdデーモンは、計測された各Java HotSpotの作成と終了をモニターし、ローカル・ホスト上で実行されているJVMにリモート・モニタリング・ツールが接続できるようにするインタフェースを提供する、RMIサーバー・アプリケーションです。

たとえば、このデーモンを使えば、jpsユーティリティでリモート・システム上のプロセスを一覧表示できます。

ノート:

FAT32ファイル・システム上では、インストゥルメンテーションにアクセスできません。