2 診断ツール
この章の構成は、次のとおりです。
診断ツールの概要
この項で説明するコマンド行ユーティリティのほとんどは、JDKに含まれているか、オペレーティング・システムのネイティブなツールやユーティリティです。
JDKコマンド行ユーティリティを使用すると、Javaランタイム環境にデプロイされているアプリケーションの問題を診断し、監視できます。
一般に、診断ツールやオプションは、様々なメカニズムを使用して報告対象の情報を取得します。それらのメカニズムは仮想マシン(VM)実装、オペレーティング・システムおよびリリースに固有のものです。通常、ツールの一部のみが、特定の時点で特定の問題に適用可能です。「-XX
」という接頭辞が付いたコマンド行オプションは、Java HotSpot VMに固有のものです。「Java HotSpot VMコマンド行オプション」を参照してください。
ノート:
-XX
オプションはJava APIの一部ではなく、リリースごとに変わる可能性があります。
これらのツールおよびオプションは、トラブルシューティングの対象となっている問題のタイプに応じて、いくつかのカテゴリに分けられます。場合によっては、1つ以上のカテゴリに分けられるツールやオプションもあります。
-
ポストモーテム診断 これらのツールおよびオプションを使用すれば、アプリケーションがクラッシュした後に問題を診断できます。「ポストモーテム診断ツール」を参照してください。
-
ハングアップ・プロセス これらのツールを使用して、ハング・アップまたはデッドロックしたプロセスを調査できます。「ハングアップ・プロセス・ツール」を参照してください。
-
モニタリング これらのツールを使用して、実行中のアプリケーションをモニターできます。「モニタリング・ツール」を参照してください。
-
その他 これらのツールやオプションを使用すれば、その他の問題を診断しやすくなります。「その他のツール、オプション、変数、およびプロパティ」を参照してください。
ノート:
この項で説明するコマンド行ユーティリティのいくつかは、試験的なものです。jstack
、jinfo
、およびjmap
ユーティリティが、試験的なユーティリティの例です。以前のjstack
、jinfo
およびjmap
ユーティリティのかわりに最新の診断ツールjcmd
の使用をお薦めします。
JDK Mission Control
JDK Mission Control (JMC)は、本番時のプロファイリングおよび診断ツールです。これには、わずかなパフォーマンス・オーバーヘッドでJavaアプリケーションをモニターおよび管理するためのツールが含まれており、本番で実行されているアプリケーションの監視に適しています。
JMCは、通常のJDKインストールには含まれません。JMCのダウンロードとドキュメントの詳細は、JDK Mission Controlのページを参照してください。
- 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を使用したフライト記録の開始
JMCアプリケーションを起動します。
起動するには、JVMブラウザでJVM/サーバーを見つけます。
JMXコンソールの「トリガー」タブを使用して、条件が満たされた場合にフライト記録が自動的に開始されるようJMCを設定できます。詳細は、トリガーを使用した自動フライト記録を参照してください。
トリガーを使用した自動フライト記録
「トリガー」タブでは、特定の条件が満たされた場合に、イベントをトリガーするルールを定義およびアクティブ化できます。たとえば、条件が満たされた場合にフライト記録を自動的に開始するようにJDK Mission Controlを設定できます。これは、特定のJVMランタイムの問題を追跡する場合に有用です。
- 条件
- アクション
- 制約
フライト記録の分析
次の項では、フライト記録を分析する様々な方法について説明します。
JMCを使用したフライト記録の分析
フライト記録ファイルをJMCで開くと、コード、メモリー、スレッド、ロック、I/Oなどの様々な領域を参照して、アプリケーションの実行時動作の様々な面を分析できます。
時間が設定された記録が終了するか、実行中の記録のダンプが作成されると、記録ファイルがJMCで自動的に開きます。ダブルクリックするか、「ファイル」メニューを使用して任意の記録ファイルを開くこともできます。フライト記録が「自動分析の結果」ページで開きます。このページは、問題を迅速に診断するのに役立ちます。たとえば、ガベージ・コレクションのチューニングまたはメモリー割当ての問題の追跡などの場合は、メモリー・ビューを使用して、個々のガベージ・コレクション・イベント、割当てサイト、ガベージ・コレクションの一時休止などに関する詳細なビューを取得できます。「I/O」ビューと「スレッド」ビューでアプリケーションのレイテンシ・プロファイルを視覚化できます。また、記録内の個々のイベントを表すビューにドリルダウンすることもできます。
「自動分析の結果」ページの表示
フライト・レコーダでは、記録からデータが抽出および分析され、「自動分析の結果」ページに色分けされたレポート・ログが表示されます。
デフォルトでは、潜在的な問題に注意が向けられるよう、黄色および赤色のスコアの結果が表示されます。レポートにすべての結果を表示するには、ページの右上にある「正常な結果の表示」」ボタン(チェック・マーク)をクリックします。同様に、結果を表として表示するには、「表」ボタンをクリックします。
ベンチマークは、主に次のものに関連する問題に分かれています:
ノート:
アウトライン・ビューで、各エントリを選択して、自動分析の各ページ間を移動できます。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
ツールの非常に役立つコマンドの一部を次に示します。
ネイティブ・メモリー・トラッキング
ネイティブ・メモリー・トラッキング(NMT)は、Java HotSpot VMの内部メモリー使用状況を追跡するJava HotSpot VM機能です。
NMTでは、非JVMコードによるメモリーの割当てを追跡しないので、ネイティブ・コードのメモリー・リークを検出するには、オペレーティング・システムでサポートされたツールの使用が必要になる場合があります。
次の項では、VM内部メモリー割当てのモニターおよびVMメモリー・リークの診断方法について説明します。
VM内部メモリーをモニターする方法
ネイティブ・メモリー・トラッキングはメモリーをモニターし、開発またはメンテナンス時にアプリケーションのメモリー使用量が増え始めないように設定できます。
NMTのメモリー・カテゴリの詳細は、表2-1を参照してください。
次の項では、NMTのサマリーまたは詳細データを取得する方法、およびサンプル出力の解釈の方法を説明します。
NMTによるメモリー・リークの検出
ネイティブ・メモリー・トラッキングを使用してメモリー・リークを検知する手順。
メモリー・リークを検出するには、次のステップを実行します。
- 次のコマンドライン・オプションを使用して、サマリーまたは詳細なトラッキングが指定されたJVMを起動します:
-XX:NativeMemoryTracking=summary
または-XX:NativeMemoryTracking=detail
。 - 初期のベースラインを設定します。NMTベースライン機能を使用して、開発とメンテナンスのときに比較するベースラインを取得するには、次を実行します:
jcmd <pid> VM.native_memory baseline
。 - 次を使用して、メモリーの変更をモニターします:
jcmd <pid> VM.native_memory detail.diff
- アプリケーションのメモリー・リークが少量の場合、それが明らかになるまで時間がかかる場合があります。
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はヒープ・メモリー使用量のグラフを示しています。
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.path
とsun.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およびヒープの視覚化を示しています。
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のネイティブ・トラブルシューティング・ツール
ツール | 説明 |
---|---|
|
メモリー・ダンプ・ファイルが正常に作成されたことを確認するコマンド行ユーティリティ。このツールは、MicrosoftのWebサイトから入手可能なDebugging Tools for Windowsダウンロードに含まれています。「Windowsでのクラッシュ・ダンプの収集」を参照してください。 |
|
Visual C++およびWin32デバッガの起動に使用可能なコマンド行ユーティリティ。 |
|
User Mode Process Dumperは、MicrosoftのWebサイトから入手可能なOEM Support Toolsダウンロードに含まれています。「Windowsでのクラッシュ・ダンプの収集」を参照してください。 |
|
Windowsデバッガは、Windowsアプリケーションまたはクラッシュ・ダンプのデバッグに使用できます。このツールは、MicrosoftのWebサイトから入手可能なDebugging Tools for Windowsダウンロードに含まれています。「Windowsでのクラッシュ・ダンプの収集」を参照してください。 |
|
メモリー割当てを追跡するための追加サポートを自動的に含めるコンパイラ・オプション。 |
表2-4では、Linuxオペレーティング・システム・バージョン10で導入または改善されたいくつかのトラブルシューティング・ツールについて説明しています。
表2-4 Linuxのネイティブ・トラブルシューティング・ツール
ツール | 説明 |
---|---|
|
C++分解シンボル名を分解解除します。このユーティリティは、Linux上の |
|
GNUデバッガ |
|
メモリー割当ての追跡 |
|
スレッド・スタックの出力 すべてのディストリビューションがデフォルトでこのツールを提供しているわけではありません。したがって、SourceForgeからのダウンロードが必要になる場合があります。 |
|
ライブラリ呼出しトレーサ すべてのディストリビューションがデフォルトでこのツールを提供しているわけではありません。したがって、SourceForgeからのダウンロードが必要になる場合があります。 |
|
GNU |
|
プロセスや他のシステム情報に関する情報が含まれている仮想ファイルシステム |
|
システム呼出しトレーサ |
|
CPU負荷が非常に高いプロセスを表示します。 |
|
プロセス、メモリー、ページング、ブロック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 ポストモーテム診断ツール
ツールまたはオプション | 説明および使用方法 |
---|---|
致命的エラー・ログ |
回復不能(致命的)なエラーが発生すると、エラー・ログが作成されます。このファイルには、致命的エラーの発生時に取得された情報が含まれています。これは多くの場合、クラッシュ発生時に最初に調べる必要がある項目です。「致命的エラー・ログ」を参照してください。 |
|
このコマンド行オプションは、VMでネイティブのメモリー不足エラーが検出された際にヒープ・ダンプを生成することを指定します。「-XX:HeapDumpOnOutOfMemoryErrorオプション」を参照してください。 |
|
このコマンド行オプションは、致命的エラーの発生時にユーザー指定の一連のスクリプトまたはコマンドを実行することを指定します。たとえばWindowsの場合、このオプションでクラッシュ・ダンプを強制するコマンドを実行できます。ポストモーテム・デバッガが構成されていないシステムでは、このオプションが非常に役立ちます。「-XX:OnErrorオプション」を参照してください。 |
|
このコマンド行オプションは、致命的エラーの発生時にプロセスを中断します。このオプションはユーザーの応答に応じて、ネイティブ・デバッガ( |
その他の |
トラブルシューティングに役立つ |
|
このユーティリティは、クラッシュから取得されたコア・ファイル、または |
|
このユーティリティは、クラッシュから取得されたコア・ファイルから、または |
|
このユーティリティは、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]+[\]または |
このキーの組合せでは、スレッド・ダンプとデッドロック検出が実行されます。Ctrl+Breakハンドラではオプションで、並行ロックとその所有者の一覧や、ヒープ・ヒストグラムを出力することもできます。「Ctrl+Breakハンドラ」を参照してください。 |
|
このユーティリティを使用してJVMに診断コマンド要求を送信し、JVMではこれらの要求を使用してフライト・レコーダからの記録を制御します。記録はフライト記録のイベントのトラブルシューティングと診断に使用します。「jcmdユーティリティ」を参照してください。 |
|
デバッガ・サポートには、 |
|
このユーティリティはJavaプロセスから構成情報を取得できます。「jinfoユーティリティ」を参照してください。 |
|
このユーティリティは、Javaプロセスからヒープ・ヒストグラムなどのメモリー・マップ情報を取得できます。 |
|
このユーティリティは、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は、プロファイリング・ツールにつきもののパフォーマンス・オーバーヘッドの問題を最小限に抑えます。 |
|
このユーティリティを使用してJVMに診断コマンド要求を送信し、JVMではこれらの要求を使用してフライト・レコーダからの記録を制御します。記録は、フライト記録のイベントを使用してJVMおよびJavaアプリケーションのトラブルシューティングと診断を行うために使用されます。「jcmdユーティリティ」を参照してください。 |
JConsoleユーティリティ |
このユーティリティは、Java Management Extensions (JMX)に基づくモニタリング・ツールです。このツールは、Java仮想マシンの組込みJMXインストゥルメンテーションを使用して、実行中のアプリケーションのパフォーマンスやリソース消費に関する情報を提供します。「JConsole」を参照してください。 |
|
このユーティリティは、Javaプロセスまたはコア・ファイルからヒープ・ヒストグラムなどのメモリー・マップ情報を取得できます。「jmapユーティリティ」を参照してください。 |
|
このユーティリティは、ターゲット・システム上で計測されたJava HotSpot VMを一覧表示します。VMが埋め込まれた環境、つまり |
|
このユーティリティは、Javaプロセスまたはコア・ファイルからJavaおよびネイティブ・スタックの情報を取得できます。「jstackユーティリティ」を参照してください。 |
|
このユーティリティは、Javaの組込みインストゥルメンテーションを使用して、実行中アプリケーションのパフォーマンスやリソース消費に関する情報を提供します。このツールは、パフォーマンスの問題、特にヒープ・サイズ決定やガベージ・コレクションに関係する問題を診断するときに使用できます。「jstatユーティリティ」を参照してください。 |
|
このユーティリティは、計測されたJava仮想マシンの作成と終了をモニターし、ローカル・ホスト上で実行されているVMにリモート・モニタリング・ツールが接続することを許可するインタフェースを提供する、Remote Method Invocation (RMI)サーバー・アプリケーションです。「jstatdデーモン」を参照してください。 |
|
このユーティリティは、ガベージ・コレクション・システムのグラフィカル表示を提供します。これは |
ネイティブ・ツール |
各オペレーティング・システムには、モニタリング目的に役立つ可能性のあるネイティブ・ツールおよびユーティリティがあります。「オペレーティング・システムのネイティブ・ツール」を参照してください。 |
その他のツール、オプション、変数、およびプロパティ
問題の診断に役立つ一般的なトラブルシューティングのツール、オプション、変数およびプロパティは、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は、プロファイリング・ツールにつきもののパフォーマンス・オーバーヘッドの問題を最小限に抑えます。 |
|
このユーティリティを使用してJVMに診断コマンド要求を送信し、JVMではこれらの要求を使用してフライト・レコーダからの記録を制御します。記録は、フライト記録のイベントを使用してJVMおよびJavaアプリケーションのトラブルシューティングと診断を行うために使用されます。 |
|
このユーティリティは、指定されたJavaプロセスの特定のJVMフラグの値を動的に設定、設定解除および変更できます。Linuxオペレーティング・システムでは、構成情報も出力できます。 |
|
このユーティリティはコマンド行スクリプト・シェルで、インタラクティブおよびバッチ・モードの両方のスクリプト実行をサポートしています。 |
|
このオプションは、Java Native Interface (JNI)を使用する、またはサード・パーティのライブラリ(一部のJDBCドライバなど)を採用するアプリケーションの問題を診断する際に役立ちます。「-Xcheck:jniオプション」を参照してください。 |
|
このオプションは、クラスのロードとアンロードのロギングを有効にします。「-verbose:classオプション」を参照してください。 |
|
このオプションは、ガベージ・コレクション情報のロギングを有効にします。「-verbose:gcオプション」を参照してください。 |
|
このオプションは、JNIのロギングを有効にします。「-verbose:jniオプション」を参照してください。 |
|
この環境変数では、ツールの初期化(具体的には |
|
このシステム・プロパティは、Java Runtime Environmentのセキュリティ・チェックが、実行中にトレース・メッセージを出力するかどうかを制御します。「java.security.debugシステム・プロパティ」を参照してください。 |