このセクションでは、問題の診断に役立つ可能性のあるいくつかのコマンド行オプションについて説明します。
「-XX」という接頭辞が付いたコマンド行オプションは、Java HotSpot 仮想マシンに固有のものです。これらのオプションの多くは、パフォーマンスチューニングや診断を行うために重要であるため、この付録で説明されています。すべての -XX オプションは、http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html に記載されています。
jinfo -flag コマンド (「2.6 jinfo ユーティリティー」) および JConsole ユーティリティー (
「2.3 JConsole ユーティリティー」) を使用すると、指定された Java プロセスの特定の Java VM フラグを動的に設定、設定解除、または変更できます。
これらのフラグの完全なリストについては、JConsole ユーティリティーの「MBean」タブを使用してください。com.sun.management ドメインにある HotSpotDiagnostic MBean の DiagnosticOptions 属性の値のリストを参照してください。これらのフラグは、次のとおりです。
HeapDumpOnOutOfMemoryError
HeapDumpPath
PrintGC
PrintGCDetails
PrintGCTimeStamps
PrintClassHistogram
PrintConcurrentLocks
-XX:+HeapDumpOnOutOfMemoryError コマンド行オプションは、Java ヒープまたは Permanent 世代からの割り当てが満たされない場合に、HotSpot VM にヒープダンプを生成するよう指示します。このオプションを使って実行するときのオーバーヘッドはないため、OutOfMemoryError が表面化するまでに長い時間のかかる本番稼動システムに役立つ可能性があります。
jconsole ユーティリティーの「MBean」タブを使用すれば、このオプションを実行時に指定することもできます。
ヒープダンプは HPROF バイナリ形式であるため、この形式をインポートできる任意のツールを使用して解析できます。たとえば、jhat ツールを使用すると、そのダンプの基本的な解析を行うことができます。「2.5 jhat ユーティリティー」を参照してください。
次の例は、このフラグセットによるメモリー不足という結果を示しています。
$ java -XX:+HeapDumpOnOutOfMemoryError -mn256m -mx512m ConsumeHeap java.lang.OutOfMemoryError: Java heap space Dumping heap to java_pid2262.hprof ... Heap dump file created [531535128 bytes in 14.691 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at ConsumeHeap$BigObject.(ConsumeHeap.java:22) at ConsumeHeap.main(ConsumeHeap.java:32)
ConsumeHeap によって Java ヒープがいっぱいになり、メモリーが使い果たされます。java.lang.OutOfMemoryError がスローされると、ヒープダンプファイルが作成されます。この場合、そのファイルは 507M バイトで、現在のディレクトリに java_pid2262.hprof として作成されます。
デフォルトでは、上記の例のように、ヒープダンプは VM の作業ディレクトリにある java_pidpid.hprof と呼ばれるファイル内に作成されます。-XX:HeapDumpPath= オプションを使用すれば、別のファイル名またはディレクトリを指定できます。たとえば、-XX:HeapDumpPath=/disk2/dumps を指定すると、ヒープダンプは /disk2/dumps ディレクトリに生成されます。
致命的エラーが発生すると、HotSpot 仮想マシンはオプションでユーザー指定のスクリプトまたはコマンドを実行できます。スクリプトまたはコマンドは、-XX:OnError=string コマンド行オプションを使って指定されます (string は単一のコマンド、またはセミコロンで区切られたコマンドのリスト)。string 内では、%p のすべての出現箇所が現在のプロセス ID (pid) に置き換えられ、%% のすべての出現箇所が単一の % に置き換えられます。次の例は、このオプションをどのように使用できるかを示しています。
Solaris OS では、pmap コマンドはプロセスのアドレス空間に関する情報を表示します。次の例では、致命的エラーが発生した場合に pmap コマンドが実行されて、そのプロセスのアドレス空間が表示されます。
java -XX:OnError="pmap %p" MyApplication
次の例は、致命的エラーが発生した場合に、どのようにして致命的エラーレポートをサポートエイリアスにメール送信できるかを示しています
java -XX:OnError="cat hs_err_pid%p.log|mail support@acme.com" \ MyApplication
Solaris OS では、gcore コマンドは指定されたプロセスのコアイメージを作成し、dbx コマンドはデバッガを起動します。次の例では、gcore コマンドが実行されてコアイメージが作成され、デバッガが起動されてそのプロセスに接続します。
java -XX:OnError="gcore %p;dbx - %p" MyApplication
次の Linux の例では、予想外のエラーが発生した場合に gdb デバッガが起動されます。gdb は、起動されると VM プロセスに接続します。
java -XX:OnError="gdb - %p" MyApplication
Windows では、ワトソン博士のデバッガをポストモーテムデバッガとして構成し、予想外のエラーが発生した場合にクラッシュダンプが作成されるようにできます。その他の詳細は、「7.4.4 Windows でのクラッシュダンプの収集」を参照してください。
Windows でクラッシュダンプを取得する別の方法は、次のように、-XX:OnError オプションを使用して userdump.exe ユーティリティーを実行することです。
java -XX:OnError="userdump.exe %p" MyApplication
userdump ユーティリティーは、Microsoft のサイトからダウンロードできる Microsoft OEM Support Tools パッケージの一部です。詳細は、「7.4.4 Windows でのクラッシュダンプの収集」を参照してください。
上記の例では、userdump.exe ユーティリティーへのパスが PATH 変数に定義されていると想定します。
オプション -XX:+ShowMessageBoxOnError が設定されているときに致命的エラーが発生した場合、HotSpot VM はその致命的エラーに関する情報を表示し、ネイティブデバッガが起動されるかどうかを指定するようユーザーに求めます。Solaris OS および Linux の場合は、その出力とプロンプトがアプリケーションコンソール (標準入力と標準出力) に送信されます。Windows の場合は、Windows メッセージボックスが表示されます。
Linux システムで発生した致命的エラーの例を次に示します。
============================================================================== Unexpected Error ------------------------------------------------------------------------------ SIGSEGV (0xb) at pc=0x2000000001164db1, pid=10791, tid=1026 Do you want to debug the problem? To debug, run 'gdb /proc/10791/exe 10791'; then switch to thread 1026 Enter 'yes' to launch gdb automatically (PATH must include gdb) Otherwise, press RETURN to abort... ==============================================================================
この場合は、SIGSEGV エラーが発生し、ユーザーは gdb デバッガが起動されてプロセスに接続するのかどうかを指定するよう求められます。ユーザーが「y」または「yes」と入力すると、gdb が起動されます (それが PATH 変数上にあると想定しています)。
Solaris OS でも、上記のようなメッセージが表示されますが、ユーザーが dbx デバッガの起動を求められる点が異なります。Windows では、メッセージボックスが表示されます。ユーザーが「YES」 ボタンを押すと、VM はデフォルトのデバッガの起動を試みます。このデバッガはレジストリ設定によって構成されます。詳細は、「7.4.4 Windows でのクラッシュダンプの収集」を参照してください。Microsoft Visual Studio がインストールされている場合、デフォルトのデバッガは通常 msdev.exe になるように構成されます。
上記の例では、プロセス ID (この場合は 10791) だけでなく、スレッド ID (この場合は 1026) も出力に含まれています。デバッガが起動された場合、デバッガの初期段階の 1 つでスレッドが選択され、そのスタックトレースが取得される可能性があります。
プロセスは応答を待っているので、ほかのツールを使ってクラッシュダンプを取得したり、プロセスの状態を問い合わせたりできます。たとえば、Solaris OS では、gcore ユーティリティーを使用してコアダンプを取得できます。
Windows では、userdump または windbg プログラムを使用して、ワトソン博士のクラッシュダンプを取得できます。windbg プログラムは、Microsoft の「Debugging Tools for Windows」に含まれています。windbg とそのダウンロード場所へのリンクの詳細は、「7.4.4 Windows でのクラッシュダンプの収集」を参照してください。windbg で、「Attach to a Process」メニューオプションを選択すると、プロセスの一覧が表示されてプロセス ID を入力するよう求められます。HotSpot VM では、プロセス ID を含むメッセージボックスが表示されます。選択すると、.dump /f コマンドを使ってクラッシュダンプを強制できます。次の例では、クラッシュダンプが crash.dump ファイル内に作成されます。
一般に、デバッガツールを利用できる開発環境では、-XX:+ShowMessageBoxOnError オプションの方が役立ちます。致命的エラーの発生時に、決められた一連のコマンドまたはスクリプトが実行される本番環境には、-XX:OnError オプションの方が適しています。
トラブルシューティングに役立つ -XX コマンド行オプションは、ほかにもいくつかあります。
-XX:OnOutOfMemoryError=string は、OutOfMemoryError がはじめてスローされたときに実行されるコマンドまたはスクリプトを指定するために使用されます。
-XX:ErrorFile=filename は、致命的エラーログファイルの場所を指定するために使用されます。「C.1 致命的エラーログの場所」を参照してください。
-XX:HeapDumpPath=path は、ヒープダンプの場所を指定するために使用されます。「B.1.2 -XX:+HeapDumpOnOutOfMemoryError オプション」を参照してください。
-XX:MaxPermSize=size は、Permanent 世代のメモリーのサイズを指定するために使用されます。「3.1.2 詳細メッセージ: PermGen space」を参照してください。
-XX:+PrintCommandLineFlags は、すべての VM コマンド行フラグの出力に使用されます。「7.3 バグレポート用のデータの収集」を参照してください。
-XX:+PrintConcurrentLocks を使用すると、Ctrl + Break ハンドラによって、各スレッドが所有する並行ロックの一覧が出力されます。
-XX:+PrintClassHistogram を使用すると、Ctrl + Break ハンドラによってヒープヒストグラムが出力されます。
-XX:+PrintGCDetails および -XX:+PrintGCTimeStamps は、ガベージコレクションに関する詳細情報の出力に使用されます。「B.2.3 -verbose:gc オプション」を参照してください。
-XX:+UseAltSigs は、(Solaris 8 および 9 OS で) SIGUSR1 および SIGUSR2 の代替シグナルを使用するよう HotSpot VM に指示するために使用されます。「6.1 Solaris OS および Linux 上でのシグナル処理」を参照してください。
-XX:+UseConcMarkSweepGC、-XX:+UseSerialGC、および -XX:+UseParallelGC は、使用されるガベージコレクションポリシーを指定します。「4.2.2 ガベージコレクション中のクラッシュ」を参照してください。
-XX オプションに加えて、ほかにも多くのコマンド行オプションがトラブルシューティング情報を提供できます。このセクションでは、これらのオプションのいくつかについて説明します。
-Xcheck:jni オプションは、Java Native Interface (JNI) を使用するアプリケーションの問題を診断するのに役立ちます。ネイティブコードにバグが含まれているせいで、HotSpot VM がクラッシュしたり、正しく動作しなかったりする場合があります。
次の例にあるように、-Xcheck:jni オプションは、アプリケーションを起動するコマンド行に追加されます。
java -Xcheck:jni MyApplication
-Xcheck:jni オプションを指定すると、VM では JNI 関数に渡された引数に対して追加の検証を行います。このオプションが無効な引数をすべて検索したり、アプリケーションコード内のロジックのバグを診断したりすることは保証されていませんが、数多くのそのような問題の診断に役立つ可能性があります。
無効な引数が検出されると、VM はアプリケーションコンソールまたは標準出力にメッセージを出力し、問題のスレッドのスタックトレースを出力して、VM を強制的に終了させます。
次の例では、null 値を許可しない JNI 関数に null 値が間違って渡されました。
FATAL ERROR in native method: Null object passed to JNI at java.net.PlainSocketImpl.socketAccept(Native Method) at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:343) - locked <0x450b9f70> (a java.net.PlainSocketImpl) at java.net.ServerSocket.implAccept(ServerSocket.java:439) at java.net.ServerSocket.accept(ServerSocket.java:410) at org.apache.tomcat.service.PoolTcpEndpoint.acceptSocket (PoolTcpEndpoint.java:286) at org.apache.tomcat.service.TcpWorkerThread.runIt (PoolTcpEndpoint.java:402) at org.apache.tomcat.util.ThreadPool$ControlRunnable.run (ThreadPool.java:498) at java.lang.Thread.run(Thread.java:536)
次の例では、jfieldID 引数を必要としていた JNI 関数に不適切な引数が渡されました。
FATAL ERROR in native method: Instance field not found in JNI get/set field operations at java.net.PlainSocketImpl.socketBind(Native Method) at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:359) - locked <0xf082f290> (a java.net.PlainSocketImpl) at java.net.ServerSocket.bind(ServerSocket.java:318) at java.net.ServerSocket.<init>(ServerSocket.java:185) at jvm003a.<init>(jvm003.java:190) at jvm003a.<init>(jvm003.java:151) at jvm003.run(jvm003.java:51) at jvm003.main(jvm003.java:30)
次のリストは、-Xcheck:jni オプションが診断に役立つ可能性のある、その他の問題の例を示しています。
間違ったスレッド用の JNI 環境が使用される場合
無効な JNI 参照が使用される場合
配列以外の型への参照が、配列型を必要とする関数に渡される場合
非 static フィールド ID が、static フィールド ID を必要とする関数に渡される場合
例外が保留になっている状態で、JNI 呼び出しが行われる場合
通常、-Xcheck:jni オプションによって検出されるエラーはすべて致命的エラーであり、それはつまり、エラーが出力されて、VM が強制終了するということです。ただし、この動作には例外が 1 つあります。JNI 呼び出しが JNI クリティカルリージョン内部で行われた場合は、次の致命的でない警告メッセージが出力されます。
Warning: Calling other JNI functions in the scope of Get/ReleasePrimitiveArrayCritical or Get/ReleaseStringCritical
JNI クリティカルリージョンは、ネイティブコードが JNI 関数 GetPrimitiveArrayCritical または GetStringCritical を使用して、Java ヒープ内の配列または文字列への参照を取得するときに作成されます。この参照は、ネイティブコードが対応する release 関数を呼び出すまで保持されます。get と release の間にあるコードは JNI クリティカルセクションと呼ばれ、その間 HotSpot VM は、ガベージコレクションの発生を許可する状態に VM を移行できません。一般的な推奨事項は、JNI クリティカルセクション内部でその他の JNI 関数、特にデッドロックを発生させる可能性のある JNI 関数を使用しないことです。したがって、-Xcheck:jni オプションによって出力された上記の警告は、潜在的な問題を示すものであり、必ずしもアプリケーションのバグを示すとはかぎりません。
JNI の詳細は、Java Native Interface のドキュメントの Web サイトを参照してください。
-verbose:class オプションは、クラスのロードおよびアンロードのロギングを有効にします。
-verbose:gc オプションは、ガベージコレクション (GC) 情報のロギングを有効にします。これをほかの HotSpot VM 固有のオプション (-XX:+PrintGCDetails や -XX:+PrintGCTimeStamps など) と組み合わせることで、GC に関する詳細情報を取得できます。その情報の出力には、各 GC の前後の世代のサイズ、ヒープの合計サイズ、昇格されたオブジェクトのサイズ、所要時間などが含まれています。
これらのオプションは、GC の解析とチューニングに関する詳細情報とともに、GC Portal のサイトに記載されています。
-verbose:gc オプションは、実行時に管理 API または JVM TI を使用して動的に有効にできます。これらの API の詳細は、「2.17 診断ツールの開発」セクションを参照してください。
jconsole モニタリング/管理ツールが管理 VM に接続されているときは、そのツールでこのオプションを有効または無効にすることもできます。「2.3 JConsole ユーティリティー」を参照してください。
-verbose:jni オプションは、JNI のロギングを有効にします。JNI またはネイティブメソッドが解決されると、HotSpot VM はアプリケーションコンソール (標準出力) にトレースメッセージを出力します。また、ネイティブメソッドが JNI RegisterNative 関数を使用して登録されるときもトレースメッセージを出力します。-verbose:jni オプションは、ネイティブライブラリを使用するアプリケーションの問題を診断するのに役立つ可能性があります。