D コマンド行オプション
この付録では、Java HotSpot VMの問題を診断する際に役立つ可能性のあるいくつかのコマンド行オプションについて説明します。
この付録の内容は次のとおりです。
Java HotSpot VMコマンド行オプション
「-XX
」という接頭辞が付いたコマンド行オプションは、Java HotSpot仮想マシンに固有のものです。これらのオプションの多くは、パフォーマンス・チューニングや診断を行うために重要であるため、この付録で説明されています。
使用可能なすべての-XX
オプションの詳細は、「Java HotSpot VMオプション」を参照してください。
jinfo -flag
コマンドを使用すると、指定されたJavaプロセスの特定のJava VMフラグの値を動的に設定、設定解除または変更できます。「jinfoユーティリティ」およびJConsoleユーティリティを参照してください。
これらのフラグの完全なリストについては、JConsoleユーティリティの「MBean」タブを使用してください。com.sun.management
ドメインにあるHotSpotDiagnostic
MBeanのDiagnosticOptions
属性の値のリストを参照してください。フラグは次のとおりです。
-
HeapDumpOnOutOfMemoryError
-
HeapDumpPath
-
PrintGC
-
PrintGCDetails
-
PrintGCTimeStamps
-
PrintClassHistogram
-
PrintConcurrentLocks
-XX:HeapDumpOnOutOfMemoryErrorオプション
このオプションは、JavaヒープまたはPermanent世代からの割当てが満たされない場合に、Java HotSpot VMにヒープ・ダンプを生成するよう指示します。このオプションを使用して実行するときのオーバーヘッドはないため、java.lang.OutOfMemoryError
が表示されるまでに長い時間のかかる本番システムに役立つ可能性があります。
JConsoleユーティリティの「MBean」タブを使用して、このオプションを実行時に指定することもできます。
次の例は、このフラグ・セットによるメモリー不足という結果を示しています。
$ 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
がスローされると、ヒープ・ダンプ・ファイルが作成されます。この場合、そのファイルは507MBで、現在のディレクトリにjava_pid2262.hprof
という名前で作成されます。
デフォルトでは、前述の例のように、ヒープ・ダンプはVMの作業ディレクトリにあるjava_pidpid.hprof
と呼ばれるファイル内に作成されます。-XX:HeapDumpPath=
オプションを使用すれば、別のファイル名またはディレクトリを指定できます。たとえば、-XX:HeapDumpPath=/disk2/dumps
を指定すると、ヒープ・ダンプは/disk2/dumps
ディレクトリに生成されます。
-XX:OnErrorオプション
致命的エラーが発生すると、Java HotSpot VMはオプションでユーザー指定のスクリプトまたはコマンドを実行できます。スクリプトまたはコマンドは、-XX:OnError=string
コマンド行オプションを使用して指定されます(string
は単一のコマンド、またはセミコロンで区切られたコマンドのリスト)。この文字列内では、%p
のすべての出現箇所が現在のPIDに置き換えられ、%%
のすべての出現箇所が単一の%
に置き換えられます。次の例は、java
ランチャを使用してMyAppという名前のJavaアプリケーションを起動するときに、このオプションをどのように使用できるかを示しています。
-
java -XX:OnError="cat hs_err_pid%p.log | mail support@example.com" MyApp
前述の例では、致命的エラーが発生した場合に、致命的エラー・ログ・ファイルの内容がサポートの別名にメール送信されます。
-
java -XX:OnError="gdb - %p" MyApp
Linuxでは、
gdb
コマンドはデバッガを起動します。前述の例では、予想外のエラーが発生した場合にgdb
デバッガが起動され、現在のプロセスに接続されます。 -
java -XX:OnError="userdump.exe %p" MyApp
Windowsでは、
userdump.exe
ユーティリティは指定されたプロセスのクラッシュ・ダンプを作成します。このユーティリティは、Windowsに付属していないため、Microsoft OEM Support Toolsパッケージの一部としてMicrosoftのWebサイトからダウンロードするようにしてください。この例では、致命的エラーが発生した場合に
userdump.exe
ユーティリティが実行されて、現在のプロセスのコア・ダンプが作成されます。ノート:
この例では、
userdump.exe
ユーティリティへのパスがPATH
変数に定義されているものと想定します。
Windowsでのクラッシュ・ダンプの作成の詳細は、「Windowsでのクラッシュ・ダンプの収集」を参照してください。
-XX:ShowMessageBoxOnErrorオプション
このオプションが設定されているときに致命的エラーが発生した場合、HotSpot VMはその致命的エラーに関する情報を表示し、ネイティブ・デバッガが起動されるかどうかを指定するようユーザーに求めます。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
変数内に設定されているものと想定)。
Windowsでは、メッセージ・ボックスが表示されます。ユーザーが「はい」をクリックした場合、VMはデフォルト・デバッガの起動を試みます。このデバッガは、「Windowsでのクラッシュ・ダンプの収集」で説明されているレジストリ設定によって構成されます。Microsoft Visual Studioがインストールされている場合、デフォルト・デバッガは通常msdev.exe
になるよう構成されます。
前述の例では、PID (pid=10791
)だけでなく、スレッドID (tid=1026
)も出力に含まれています。デバッガが起動された場合、デバッガの初期ステップの1つでスレッドが選択され、そのスタック・トレースが取得される可能性があります。
プロセスは応答を待っているので、他のツールを使用してクラッシュ・ダンプを取得したり、プロセスの状態を問い合せたりできます。
Windowsでは、userdump
またはwindbg
プログラムを使用して、ワトソン博士のクラッシュ・ダンプを取得できます。windbg
ユーティリティはMicrosoftのDebugging Tools for Windowsに含まれており、「Windowsでのクラッシュ・ダンプの収集」で説明されています。windbg
で、「Attach to a Process」メニュー・オプションを選択すると、プロセスの一覧が表示されてPIDを入力するよう求められます。HotSpot VMでは、PIDを含むメッセージ・ボックスが表示されます。PIDを選択した後、.dump /f
コマンドを使用してクラッシュ・ダンプを強制できます。例D-1は、crash.dump
というファイルに作成されたクラッシュ・ダンプの例です。
一般に、デバッガ・ツールを利用できる開発環境では、-XX:+ShowMessageBoxOnError
オプションの方が役立ちます。致命的エラーの発生時に、決められた一連のコマンドまたはスクリプトが実行される本番環境には、-XX:OnError
オプションの方が適しています。
その他の-XXオプション
トラブルシューティング時に役立つ可能性のある-XX
コマンド行オプションは、他にもいくつかあります。
-
-XX:OnOutOfMemoryError
=string
このオプションを使用すると、
java.lang.OutOfMemoryError
がスローされたときに実行されるコマンドまたはスクリプトを指定できます。 -
-XX:ErrorFile
=filename
このオプションは、致命的エラー・ログ・ファイルの場所を指定するために使用できます。「致命的エラー・ログの場所」を参照してください。
-
-xx:HeapDumpPath
=path
このオプションは、ヒープ・ダンプの場所を指定するために使用できます。「-XX:HeapDumpOnOutOfMemoryErrorオプション」を参照してください。
-
-XX:MaxPermSize
=size
このオプションは、Permanent世代メモリーのサイズを指定するために使用できます。「java.lang.OutOfMemoryErrorエラー」を参照してください。
-
-XX:+PrintCommandLineFlags
このオプションはすべてのVMコマンド行フラグを出力するために使用できます。「バグ・レポート用のデータの収集」を参照してください。
-
-XX:+PrintConcurrentLocks
このオプションを使用すると、Ctrl+Breakハンドラによって、各スレッドが所有する並行ロックの一覧が出力されます。
-
-XX:+PrintClassHistogram
このオプションを使用すると、Ctrl+Breakハンドラによって、ヒープ・ヒストグラムが出力されます。
-
-XX:+PrintGCDetails
and-XX:+PrintGCTimeStamps
これらのオプションは、ガベージ・コレクションの詳細情報の出力に使用できます。「-verbose:gcオプション」を参照してください。
-
-XX:+UseConcMarkSweepGC
,-XX:+UseSerialGC
and-XX:+UseParallelGC
このオプションは、使用されるガベージ・コレクション・ポリシーを指定するために使用できます。「ガベージ・コレクション中のクラッシュの回避」を参照してください。
その他のコマンド行オプション
-XX
オプションに加えて、ほかにも多くのコマンド行オプションがトラブルシューティング情報を提供できます。
このセクションでは、これらのオプションのいくつかについて説明します。
-Xcheck:jniオプション
このオプションは、Java Native Interface (JNI)を使用するアプリケーションの問題を診断する際に役立ちます。ネイティブ・コードにバグが含まれているせいで、HotSpot VMがクラッシュしたり、正しく動作しなかったりする場合があります。
次の例にあるように、-Xcheck:jni
オプションは、アプリケーションを起動するコマンド行に追加されます。
java -Xcheck:jni MyApp
-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)
- 呼出しを行うスレッドがJVMにアタッチされていない
- 呼出しを行うスレッドが、別のスレッドに属するJNIEnvを使用している
- パラメータ検証チェックが失敗する:
- jfieldIDまたはjmethodIDが無効として検出される。次に例を示します。
- 間違ったタイプ
- 間違ったクラスに関連付けられる
- 間違ったタイプのパラメータが検出される
- 無効なパラメータ値が検出される。次に例を示します。
- 許可されないNULL
- 範囲外の配列索引、またはフレーム容量
- UTF-8以外の文字列
- 無効なJNI参照
- 対応するGetXXX関数で生成されていないパラメータに対してReleaseXXX関数を使用しようとする
- jfieldIDまたはjmethodIDが無効として検出される。次に例を示します。
- 以前のJNI呼出しからの保留中の例外をチェックせずにJNI呼出しが行われ、例外が保留中の可能性がある場合に現在の呼出しが安全ではない
- JNI関数の終了時に存在するJNIローカル参照の数が、使用可能であることが保証されている数を超えている。「EnsureLocalcapacity関数」を参照してください
- クラス・ディスクリプタが、そうすべきではない場合に装飾された形式(Lname;)になっている
- NULLパラメータは使用できるが、その使用に疑問がある
- Get/ReleasePrimitiveArrayCriticalまたはGet/ReleaseStringCriticalのスコープ内で他の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
オプションによって出力された上記の警告は、潜在的な問題を示すものであり、必ずしもアプリケーションのバグを示すとはかぎりません。
-verbose:classオプション
このオプションは、クラスのロードとアンロードのロギングを有効にします。
-verbose:gcオプション
このオプションは、ガベージ・コレクション(GC)情報のロギングを有効にします。これを他のHotSpot VM固有のオプション(-XX:+PrintGCDetails
や-XX:+PrintGCTimeStamps
など)と組み合せることで、GCに関する詳細情報を取得できます。その情報の出力には、各GCの前後の世代のサイズ、ヒープの合計サイズ、昇格されたオブジェクトのサイズ、所要時間などが含まれています。
これらのオプションおよびGCの解析とチューニングの詳細は、GC Portalの記事に記載されています。
-verbose:gc
オプションは、実行時に管理APIまたはJVM TIを使用して動的に有効にできます。「カスタム診断ツール」を参照してください。
JConsoleモニタリングおよび管理ツールが管理VMに接続されているときは、そのツールでこのオプションを有効または無効にすることもできます。「JConsole」を参照してください。
-verbose:jniオプション
このオプションは、JNIのロギングを有効にします。JNIまたはネイティブ・メソッドが解決されると、HotSpot VMはアプリケーション・コンソール(標準出力)にトレース・メッセージを出力します。また、ネイティブ・メソッドがJNI RegisterNative
関数を使用して登録されるときもトレース・メッセージを出力します。-verbose:jni
オプションは、ネイティブ・ライブラリを使用するアプリケーションの問題を診断する際に役立つ可能性があります。