Javaアプリケーション用のデバッグツールを作成することを考えています。
Exception.printStackTrace()
のように、しかし実際に例外をスローせずに、スタックトレースを取得できるかどうか疑問に思っていますか?
私の目標は、特定のメソッドでスタックをダンプして、メソッドの呼び出し元を確認することです。
Thread.getAllStackTraces()
を試して、生きているすべてのスレッドのスタックトレースのマップを取得することもできます。
はい、単に使用します
Thread.dumpStack()
(Ramの提案のように、システム内のすべてのスレッドではなく)現在のスレッドのみのトレースが必要な場合は、次のようにします。
Thread.currentThread(). getStackTrace()
呼び出し元を見つけるには、次を実行します。
private String getCallingMethodName() {
StackTraceElement callingFrame = Thread.currentThread().getStackTrace()[4];
return callingFrame.getMethodName();
}
そして、呼び出し元を知る必要があるメソッド内からそのメソッドを呼び出します。ただし、警告の言葉:リスト内の呼び出しフレームのインデックスは、JVMによって異なる場合があります!それはすべて、トレースが生成されるポイントに到達する前にgetStackTrace内にある呼び出しの層の数に依存します。より堅牢なソリューションは、トレースを取得し、getCallingMethodNameのフレームを探してそれを反復処理し、さらに2つのステップを実行して真の呼び出し元を見つけることです。
次のようなスタックトレースを取得できます。
Throwable t = new Throwable();
t.printStackTrace();
フレームにアクセスする場合は、t.getStackTrace()を使用してスタックフレームの配列を取得できます。
ホットスポットコンパイラが最適化に忙しい場合は、このスタックトレース(他のフレームワークと同様)で一部のフレームが失われる可能性があることに注意してください。
Thread.dumpStack()が実際に例外をスローすることに注意してください。
new Exception("Stack trace").printStackTrace();
QUITシグナルをプロセスに送信することにより、実行中のJavaプロセスでThread.getAllStackTraces()を実行するJVMにシグナルを送信することもできます。
Unix/Linuxの場合:
kill -QUIT process_id
、ここでprocess_idは、Javaプログラムのプロセス番号です。
Windowsでは、アプリケーションでCtrl-Breakを押すことができますが、通常はコンソールプロセスを実行していない限り表示されません。
JDK6では、jstackコマンドという別のオプションが導入されました。このオプションは、コンピューターで実行中のJDK6プロセスのスタックを表示します。
jstack [-l] <pid>
これらのオプションは、実稼働環境で実行されており、簡単に変更できないアプリケーションに非常に役立ちます。これらは、実行時のデッドロックやパフォーマンスの問題を診断するのに特に役立ちます。
http://Java.Sun.com/developer/technicalArticles/Programming/Stacktrace/http://Java.Sun.com/javase/6/docs/technotes/tools/share /jstack.html
Java 9は StackWalker
を導入し、スタックを歩くためのクラスをサポートしました。
Javadocのスニペットを次に示します。
walk
メソッドは、現在のスレッドに対してStackFrames
の順次ストリームを開き、指定された関数を適用してStackFrame
ストリーム。ストリームは、スタックが生成された実行ポイントを表す一番上のフレームから一番下のフレームまで、順番にスタックフレーム要素を報告します。 walkメソッドが戻ると、StackFrame
ストリームは閉じられます。閉じたストリームを再利用しようとすると、IllegalStateException
がスローされます。...
現在のスレッドのトップ10スタックフレームのスナップショットを作成するには、
List<StackFrame> stack = StackWalker.getInstance().walk(s -> s.limit(10).collect(Collectors.toList()));
キャプチャ出力が必要な場合
StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
コードでこれを行う必要さえありません。 Java HPROFをプロセスにアタッチし、任意の時点でControl- \を押すと、ヒープコード、実行中のスレッドなどを出力できます。 、Java 6はGUI jconsoleに付属していますが、HPROFは非常に便利であると感じています。