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


25

システム管理者として、私は時々、プログラムが異常に動作する状況に直面しますが、エラーをまったく作成しないか、意味のないエラーメッセージを作成します。

過去-javaが登場する前に-2つの対策がありました。

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

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

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

回答:


16

ckhanが述べたようjstackに、JVMのすべてのアクティブなスレッドの完全なスタックトレースを提供するため、素晴らしいです。同じことは、SIGQUITを使用してJVMのstderrで取得できます。

別の便利なツールはjmap、プロセスのPIDを使用してJVMプロセスからヒープダンプを取得できます。

jmap -dump:file=/tmp/heap.hprof $PID

このvisualvmヒープダンプは、次のようなツールで読み込むことができます(現在、jvisualvmという名前の標準Oracle java sdkインストールの一部です)。さらに、VisualVMは実行中のJVMに接続し、内部CPU使用率、スレッド数、ヒープ使用率のグラフ表示など、JVMに関する情報を表示できます。リークの追跡に最適です。

別のツール、jstatは、数値引数(たとえばvmstat 3)を指定して実行した場合のvmstatと同様に、JVMのガベージコレクション統計を一定期間収集できます。

最後に、Javaエージェントを使用して、ロード時にすべてのオブジェクトのすべてのメソッドでインストルメンテーションをプッシュすることができます。ライブラリjavassistは、これを非常に簡単にするのに役立ちます。したがって、独自のトレースを追加することは可能です。それが難しいのは、常にではなく、必要なときにのみトレース出力を取得する方法を見つけることです。これにより、JVMのクロール速度が低下する可能性があります。dtraceこのような方法で機能するプログラムがあります。試しましたが、あまり成功しませんでした。JVMのブートストラップに必要なクラスはエージェントがインストルメントできるようになる前にロードされるため、エージェントはすべてのクラスをインストルメントできないことに注意してください。

私の提案 -VisualVMから始めて、JVMの現在のスレッドと重要な統計を表示できるため、知っておくべきことを教えてくれるかどうかを確認してください。


ところで、これは素晴らしい質問です。もっと多くの人が他のアイデアで答えを追加することを願っています。Javaで長年作業している人々にトレースについて尋ねてきたとき、彼らは私に空白の視線を与えました。おそらく、彼らはstraceの素晴らしさを知らないだけでしょう。

10

Linuxシステムで問題が発生したプログラムをデバッグするとき、同じ無駄に、システムで実行中のJVMをデバッグするために同様のツールを使用できます。

ツール#1-jvmtop

に似てtopjvmtopを使用して、システムで実行中の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 MonitorはEclipseと統合されたJavaプロファイラーで、JavaアプリケーションのCPU、スレッド、メモリ使用量を監視します。これを使用して、localhostで実行中のJVMを自動的に見つけるか、port @ hostを使用してリモートJVMに接続できます。

jvmmonitorのss

ツール#3-visualvm

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

アプリケーションのパフォーマンスをプロファイルするか、メモリ割り当てを分析します。

visualvm#2のss

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

visualvm#3のss

参照資料


4

検討してくださいjstack。とはまったく一致しませんがstrace、より多くの- pstackアナログですが、少なくとも時間内のスナップショットの写真を提供します。必要に応じて、それらをつなぎ合わせて粗雑なトレースを取得できます。

このSO記事の提案も参照してください:https : //stackoverflow.com/questions/1025681/call-trace-in-java


2

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スタックを取得するために使用することもできますが、JVMの前に SystemTapを起動した場合にのみ機能します。


SystemTapはすべてのメソッドをトレースすることに注意してください。また、メソッドの引数を取得することもできません。もう1つのオプションは、JVMTIと呼ばれるJVM独自のトレース機能を使用することです。最も有名なJVMTI実装の1つはBTraceです。


0

Jackplayを試してみることをお勧めします。Jackplayは、コードの変更や再デプロイを行わずにメソッドの開始と終了をトレースできるJVMトレースツールです。


実行中のJVMに接続することはできません。それとは別に-面白いツール
ニルス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.