Java内からJavaを監視する
-
06-07-2019 - |
質問
プログラムのメソッド呼び出しをツリーのブランチとして表示することにより、Javaプログラムの簡単な視覚化を記述したいと思います。これは、プログラム自体が何をしているかを視覚化に伝えることで非常に簡単に行うことができますが、私が変更するものだけでなく、任意のJavaメソッド/クラスでこれを実行できるようにしたいです。
必要なのは、プログラムが呼び出すメソッドや、そのメソッド内で呼び出されるメソッドなどを監視する機能です。明らかに、スタックトレースはまさにこの機能を提供します:
java.lang.NullPointerException
at MyClass.mash(MyClass.java:9)
at MyClass.crunch(MyClass.java:6)
at MyClass.main(MyClass.java:3)
それで、監視したいプログラムをスレッドで実行し、そのスレッドのスタックを見るだけだと考えました。ただし、スレッドクラスはこれを実際にはサポートしていません。現在のスタックの印刷のみをサポートしています。
もちろん、スレッドがそのスタックを my PrintStreamに印刷するように、SystemクラスのPrintStreamを単に変更することを考えましたが、これはちょっと間違っているように感じます。
これを行うより良い方法はありますか?使用できる既存のクラス/メソッドはありますか?
また、スレッドクラスがどのようにスタックを印刷するかを確認するために、現在Javaソースコードをダウンロードしているので、スレッドをサブクラス化し、独自のgetStack()メソッドでdumpStack()メソッドを模倣できます。
解決 2
ソースコードを調べてみると、スレッドクラスにpublic StackTraceElement [] getStackTrace()メソッドがあることに気付きましたが、これは読んでいたドキュメントにはありませんでした。今、私は愚かな感じがします。
そう、それが解決策のようです。
他のヒント
最新のJavaリリースに同梱されているVisualVMもご覧ください。
1つのアプローチは、 BCEL のようなものを使用して、ターゲットバイトコードを前処理して呼び出しを挿入することです。すべてのメソッドの入り口と出口で独自のコード(例外出口をキャッチするためにtry / finallyブロックでメソッド全体をラップして出口を実行するのがおそらく最善です)。これから、発生したとおりにコールツリーを推測できます。
ThreadMXBean クラスをご覧ください。あなたが必要です。基本的に、あなた:
- ManagementFactory.getThreadMXBean()を呼び出して、ThreadMXBeanのインスタンスを取得します。
- 結果のThreadMXBeanでgetAllThreadIds()を呼び出して、現在のスレッドを列挙します。
- getThreadInfo()を呼び出して、指定されたスレッドのリストから上位n個のスタックトレース要素を取得します。