web-dev-qa-db-ja.com

Javaプログラムをトレースする方法は?

システム管理者として、プログラムを異常に動作させながら、まったくエラーを生成したり、意味のないエラーメッセージを生成したりする状況に直面することがあります。

過去-Javaが登場する前-2つの対策がありました:

  1. 他に何も役に立たない場合-RTFM ;-)
  2. 1.でも解決しない場合-システムコールをトレースして、何が起こっているかを確認します

私は通常strace -f Linuxでのこのタスク用(他のOSにも同様のトレースツールがあります)。これは通常、昔ながらのプログラムでうまく機能しますが、Java-プロセスで同じことを行うと、トレースが非常にあいまいになります。実際のアクションとは無関係のように見えるシステムコールが非常に多いため、そのようなダンプを検索するのはひどいものです。

(ソースコードが利用できない場合)それを行うより良い方法はありますか?

25
Nils

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の現在のスレッドと重要な統計を表示できるため、知っておくべきことがわかるかどうかを確認します。

16
ash

Linuxシステムでうまくいかなかったプログラムをデバッグするときと同じように、同様のツールを使用して、システムで実行中のJVMをデバッグできます。

ツール#1-jvmtop

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

ツール#2-jvmmonitor

別の方法は、 jvmmonitor を使用することです。 JVMモニターは、JavaプロファイラーがEclipseに統合され、JavaアプリケーションのCPU、スレッド、およびメモリ使用量を監視します。これを使用して、実行中のJVMを自動的に見つけることができますlocalhostまたはport @ Hostを使用してリモートJVMに接続できます。

ss of jvmmonitor

ツール#3-visualvm

visualvm はおそらく、JVMの問題をデバッグするときに到達する「ツール」です。その機能セットはかなり深く、内部を非常に詳細に見ることができます。

アプリケーションのパフォーマンスのプロファイルまたはメモリ割り当ての分析:

ss of visualvm #2

スレッドダンプを取得して表示します:

ss of visualvm #3

参考文献

10
slm

jstack を検討してください。 straceに完全に一致するわけではありませんが、 pstack -analogの詳細は表示されますが、少なくともスナップショットの画像が表示されます。必要に応じて、一緒に文字列を作成して、大まかなトレースを取得できます。

この提案もご覧くださいSO記事: https://stackoverflow.com/questions/1025681/call-trace-in-Java

4
ckhan

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 です。

2
myaut

Jackplay を試すことをお勧めします。これは、コードを変更したり再デプロイしたりせずにメソッドのエントリと終了をトレースできるJVMトレースツールです。

0
alfredx