システム管理者として、プログラムを異常に動作させながら、まったくエラーを生成したり、意味のないエラーメッセージを生成したりする状況に直面することがあります。
過去-Javaが登場する前-2つの対策がありました:
私は通常strace -f
Linuxでのこのタスク用(他のOSにも同様のトレースツールがあります)。これは通常、昔ながらのプログラムでうまく機能しますが、Java-プロセスで同じことを行うと、トレースが非常にあいまいになります。実際のアクションとは無関係のように見えるシステムコールが非常に多いため、そのようなダンプを検索するのはひどいものです。
(ソースコードが利用できない場合)それを行うより良い方法はありますか?
Ckhanが述べたように、jstack
は、JVM内のすべてのアクティブなスレッドの完全なスタックトレースを提供するため、優れています。同じことは、SIGQUITを使用してJVMのstderrで取得できます。
もう1つの便利なツールはjmap
であり、プロセスのPIDを使用してJVMプロセスからヒープダンプを取得できます。
jmap -dump:file=/tmp/heap.hprof $PID
このヒープダンプは、visualvm
(標準のOracle Java sdk install、jvisualvmという名前の一部になっています)などのツールにロードできます。さらに、VisualVMは実行中のJVMと、内部CPU使用率、スレッド数、ヒープ使用率のグラフの表示を含む、JVMに関する情報の表示-リークの追跡に最適です。
別のツールjstat
は、数値引数を指定して実行すると、vmstatのように、一定期間にわたってJVMのガベージコレクション統計を収集できます(例:vmstat 3
)。
最後に、ロード時にすべてのオブジェクトのすべてのメソッドでJava Agent to Push Instrumentationを使用できます。ライブラリjavassist
を使用すると、これを非常に簡単に実行できます。 。したがって、独自のトレースを追加することは現実的です。これで難しいのは、常にではなく、必要なときにだけトレース出力を取得する方法を見つけることです。これにより、JVMのクロールが遅くなる可能性があります。プログラムがあります。 dtrace
と呼ばれ、このような方法で機能します。私は試しましたが、あまり成功しませんでした。bootstrap the JVMは、エージェントがインスツルメントする前にロードされますが、それらのクラスにインスツルメンテーションを追加するには遅すぎます。
私の提案-VisualVMから始めて、JVMの現在のスレッドと重要な統計を表示できるため、知っておくべきことがわかるかどうかを確認します。
Linuxシステムでうまくいかなかったプログラムをデバッグするときと同じように、同様のツールを使用して、システムで実行中のJVMをデバッグできます。
top
と同様に、 jvmtop を使用して、システムで実行中のJVM内でどのクラスに達しているかを確認できます。インストールしたら、次のように呼び出します。
$ jvmtop.sh
その出力は、ツールtop
のように同様にスタイル設定されます。
JvmTop 0.8.0 alpha AMD64 8 cpus, Linux 2.6.32-27, load avg 0.12
http://code.google.com/p/jvmtop
PID MAIN-CLASS HPCUR HPMAX NHCUR NHMAX CPU GC VM USERNAME #T DL
3370 rapperSimpleApp 165m 455m 109m 176m 0.12% 0.00% S6U37 web 21
11272 ver.resin.Resin [ERROR: Could not attach to VM]
27338 WatchdogManager 11m 28m 23m 130m 0.00% 0.00% S6U37 web 31
19187 m.jvmtop.JvmTop 20m 3544m 13m 130m 0.93% 0.47% S6U37 web 20
16733 artup.Bootstrap 159m 455m 166m 304m 0.12% 0.00% S6U37 web 46
別の方法は、 jvmmonitor を使用することです。 JVMモニターは、JavaプロファイラーがEclipseに統合され、JavaアプリケーションのCPU、スレッド、およびメモリ使用量を監視します。これを使用して、実行中のJVMを自動的に見つけることができますlocalhostまたはport @ Hostを使用してリモートJVMに接続できます。
visualvm はおそらく、JVMの問題をデバッグするときに到達する「ツール」です。その機能セットはかなり深く、内部を非常に詳細に見ることができます。
アプリケーションのパフォーマンスのプロファイルまたはメモリ割り当ての分析:
スレッドダンプを取得して表示します:
jstack
を検討してください。 strace
に完全に一致するわけではありませんが、 pstack
-analogの詳細は表示されますが、少なくともスナップショットの画像が表示されます。必要に応じて、一緒に文字列を作成して、大まかなトレースを取得できます。
この提案もご覧くださいSO記事: https://stackoverflow.com/questions/1025681/call-trace-in-Java
RHEL OpenJDK(または同様のことですが、OracleのJDKではない)を使用している場合は、 SystemTap を使用できます。
一部のプローブは、Javaコマンドラインオプション_-XX:+DTraceMethodProbes
_、_-XX:+DTraceAllocProbes
_、_-XX:+DTraceMonitorProbes
_)を使用して有効にします。これらのプローブを有効にすると、プログラムのパフォーマンスに大きく影響することに注意してください。
以下はSystemTapスクリプトの例です。
_#!/usr/bin/stap
probe hotspot.class_loaded {
printf("%12s [???] %s\n", name, class);
}
probe hotspot.method_entry,
hotspot.method_return {
printf("%12s [%3d] %s.%s\n", name, thread_id, class, method);
}
probe hotspot.thread_start,
hotspot.thread_stop {
printf("%12s [%3d] %s\n", name, id, thread_name);
}
probe hotspot.monitor_contended_enter,
hotspot.monitor_contended_exit {
printf("%12s [%3d] %s\n", name, thread_id, class);
}
_
jstack()
を使用してJavaプロセスのスタックを取得することもできますが、SystemTapbeforeJVM。
SystemTapはeveryメソッドをトレースすることに注意してください。また、メソッドの引数を取得することもできません。別のオプションは、JVMTIと呼ばれるトレースのJVM独自の機能を使用することです。最も有名なJVMTI実装の1つは BTrace です。
Jackplay を試すことをお勧めします。これは、コードを変更したり再デプロイしたりせずにメソッドのエントリと終了をトレースできるJVMトレースツールです。