1 トラブルシューティングのためのJavaの準備

この章では、よりよいトラブルシューティング手法のためのJavaとJavaアプリケーションの設定指針について説明します。これらの事前のJavaの設定は、Javaおよびアプリケーションの問題のデバッグおよび絞込みに役立ちます。すべての提案がすべてのアプリケーションに適用されるものではありません。

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

トラブルシューティングのためのJavaの設定

トラブルシューティングの関連データを収集可能にするためのJava環境およびコマンド行オプションを設定します。

Javaを設定する手順は次のとおりです。

  1. Javaのバージョンの更新: 修正されたJavaの問題のトラブルシューティングに時間をかけることを避けるために、最新のJavaバージョンを使用します。多くの場合、Javaランタイムのバグに起因する問題は、最新のアップデート・リリースで修正されています。最新のJavaバージョンの使用により、いくつかの一般的な既知の問題を回避できます。
  2. デバッグのためのJava環境の設定: 大きなJavaアプリケーションの設定、ランチャ・スクリプトによるアプリケーションの起動、または複数のマシンで分散Javaを実行するときは次のシナリオを検討してください。
    1. Javaバージョンを簡単に変更できるようにする: Javaの最新バージョンにより、多くの実行時の問題を回避できます。スクリプトを実行してアプリケーションを起動する場合は、Javaパスの更新が必要となる場所が1箇所のみであることを確認してください。分散システムで実行する場合は、すべてのマシンのJavaバージョンが変更される簡単な方法を考えます。
    2. Javaのコマンド行オプションを簡単に変更できるようにする: たとえば、詳細出力の追加、機能をオフにする、パフォーマンスの向上のためのJavaのチューニングなどのために、トラブルシューティング中にJavaオプションを変更する場合があります。これらの変更に備えてシステムを準備しておきます。
      テスト・フレームワークやクラウド・ソリューションなどでJavaアプリケーションをリモートで実行する場合にも、Javaフラグを簡単に変更できることを確認してください。問題を再現するために、アプリケーションにコマンド行パラメータを指定したり、フラグをすぐに試してみたい場合があります。これらの変更が簡単に行えるようにシステムを準備します。

JVMのトラブルシューティングのためのオプションおよびフラグの有効化

トラブルシューティングの関連データを収集可能にするためのJVMオプションやフラグを設定します。

収集するデータはシステムごとに異なり、問題が発生した場合に使用するデータによっても異なります。次のデータの収集を検討します。

  1. コア・ファイルを有効にする: たとえば、セグメンテーション・フォルトによってJavaがクラッシュした場合、OSはディスクにコア・ファイル(メモリーの完全なダンプ)を保存します。Linuxでは、コア・ファイルがデフォルトで無効になっている場合があります。Linux上のコア・ファイルを有効にするには、通常、アプリケーション・コマンドを起動する前にulimit -c unlimitedを実行するだけで十分です。一部のシステムでは、これらの制限の扱い方が異なる場合があります。

    注意:

    コア・ファイルは、特に大きなJavaヒープで実行する場合、多くのディスク領域を取ります。

    コア・ファイルを有効にするかどうかを決定するときは、システムでクラッシュが発生した場合の対処方法を検討します。コア・ファイルを参照したいと思いますか。多くのJavaユーザーには、コア・ファイルは大して役に立ちません。ただし、クラッシュが発生した場合に、gdbなどのネイティブ・デバッガまたはServiceability Agentを使用してデバッグする場合は、アプリケーションを起動する前にコア・ファイルを有効にしてください。

    多くの場合、クラッシュを再現するのは困難です。そのため、アプリケーションを起動する前にコア・ファイルを有効にします。

  2. JVMフラグに-XX:+HeapDumpOnOutOfMemoryErrorを追加する: -XX:+HeapDumpOnOutOfMemoryErrorフラグは、アプリケーションでOutOfMemoryErrorが発生した場合に、ディスクにJavaヒープのダンプを保存します。

    ヒープ・ダンプは、特に大きなJavaヒープで実行する場合、コア・ファイルと同様に非常に大きくなる可能性があります。

    再び、アプリケーションでOutOfMemoryErrorが発生した場合の対処方法を考えます。エラーの発生時に、ヒープを検査したいと思いますか。その場合、アプリケーションで予想外のOutOfMemoryErrorが発生したときにこのデータを取得するために、フラグをデフォルトで設定します。

  3. フライトの連続記録を実行する: 連続フライト記録を実行するためにJavaを設定します。

    連続フライト記録は、フライト・レコーダ・イベントの循環バッファです。アプリケーションで問題が発生した場合は、最後の1時間の実行からデータをダンプできます。フライト・レコーダ・イベントは、メモリー・リーク、ネットワーク・エラー、高いCPU使用率、スレッドのブロックなど、幅広い問題のデバッグに役立ちます。

    連続フライト記録を使用した実行のオーバーヘッドは非常に低いです。「フライト記録の生成」を参照してください。

  4. JVMコマンド行に-verbosegcを追加する: -verbosegcフラグは、Javaガベージ・コレクタの基本情報をログします。このログは、次のことを見つけるのに役立ちます。
    • ガベージ・コレクションの実行に時間がかかっているかどうか。

    • 空きメモリーが経時的に減少しているかどうか。

    ガベージ・コレクタのログは、アプリケーションがOutOFMemoryErrorをスローするか、パフォーマンスの問題が発生した場合、問題の診断に役立ちます。したがって、-verbosegcフラグをデフォルトでオンにすると、問題のトラブルシューティングに役立ちます。

    注意:

    アプリケーションの再起動によって前のログが削除されないように、ログ・ローテーションを使用します。JDK7以降では、UseGClogFileRotationフラグおよびNumberOfGCLogFilesフラグをログ・ローテーションの設定に使用できます。これらのフラグの詳細は、Java HotSpot VMのデバッグ・オプションに関する項を参照してください。
  5. JavaバージョンおよびJVMフラグを出力する: Javaのバグを提出したりフォーラムで助けを求める前に、ログ・ファイルの基本情報がすぐわかるようにしておきます。たとえば、Javaバージョンと使用しているJVMフラグを印刷すると役立ちます。

    アプリケーションをスクリプトで起動する場合は、実行する前に、java -versionを実行してJavaバージョンを印刷し、コマンド行を印刷してください。または、JVMの引数に-XX+PrintCommandLineFlags-showversionを追加することもできます。

  6. リモート・モニタリングのためのJMXの設定: JMXは、Visual VMなどのツールを使用してJavaアプリケーションにリモート接続するために使用できます。アプリケーションを実行しているマシン上でこれらのツールを実行できる場合を除き、これを設定すると、後のアプリケーションのモニター、診断コマンドの送信、フライト記録の管理などに役立ちます。JMXを有効化した場合、パフォーマンス上のオーバーヘッドはありません。

    別の方法は、Javaアプリケーションの起動後にJMXを有効にする方法で、ManagementAgent.start診断コマンドを使用します。コマンドで送信できるフラグの一覧については、jcmd <pid> help ManagementAgent.startを実行してください。

    「jcmdユーティリティ」を参照してください。

関連データの収集

アプリケーションで問題が発生した場合、問題の詳細をデバッグするには、特に再起動により前のファイルが削除される場合は、システムを再起動する前に関連データを収集してください。

  • 次のファイルを収集することが重要です。
    • クラッシュの問題に関するコア・ファイル。

    • Javaのクラッシュの場合に出力されるhs_errテキスト・ファイル。

    • ログ・ファイル: Javaおよびアプリケーションのログ。

    • -XX:+HeapDumpOnOutOfMemoryErrorのJavaヒープ・ダンプ。

    • フライト記録(有効な場合)。問題によってアプリケーションが終了しなかった場合は、連続記録をダンプします。

  • アプリケーションが応答しない場合は、次のファイルを収集します。
    • スタック・トレース: システムを再起動する前に、jcmd <pid> Thread.printを使用して複数のスタック・トレースを取ります。

    • フライト記録をダンプします(有効な場合)。

    • コア・ファイルの強制: アプリケーションを正常に閉じることができない場合は、Linuxシステムで、アプリケーションを停止し、kill -6 <pid>を使用してコア・ファイルを強制します。

デバッグが容易なJavaアプリケーションの作成

ロギング・フレームワークの使用は、後のデバッグを可能にするための良い方法です。

特定のモジュールで問題が発生する場合は、そのモジュールのロギングを有効にできる必要があります。また、情報、デバッグ、トレースなどの異なるロギング・レベルの指定も役立ちます。