実行中のJVMで実行中のインスタンスを見つける
-
05-07-2019 - |
質問
特定のクラスのインスタンスを実行中にハンドルを取得することが可能かどうか疑問に思っています。これを引き起こした特定の問題は、実行中のスレッド数が多いためにうまく終了しないアプリケーションでした。
はい、あなたはtheadをデーモン化できることを知っています、そしてそれらはアプリケーションの出口を遅らせません。しかし、それが可能かどうか疑問に思いました。最も近いものはクラスローダー(保護されています!) findLoadedClass 。ただし、これを行うには独自のクラスローダーを実行する必要があります。
関連するメモでは、これはプロファイリングツールがオブジェクトハンドルを追跡する方法ですか?独自のカスタムクラスローダーを実行しますか?または私が見ていないいくつかの素敵なトリッキーな方法がありますか?
解決
OSのような* NIXでkill -QUIT <pid>
を使用するか、Windowsコンソールでアプリケーションを実行してCtrl-Pause
を押すと、実行中のすべてのスレッドのスタックトレースをstdoutに実際に取得できます(別のポスターノートとして。 )
しかし、あなたはそれを行うためのプログラム的な方法を求めているようです。したがって、本当に必要なのは、現在の呼び出しスタックに含まれるすべてのスレッドのセットであり、特定のクラスの1つ以上のメソッドが含まれていることです...
JVMTIへの呼び出しを伴わない最良の方法は、実行中のすべてのスレッドのスタックを検査することです。私はこれを試していませんが、Java 1.5以降で動作するはずです。これは、定義上、AT ALLスレッドセーフではないことに注意してください(実行中のスレッドのリストとその現在のスタックトレースは、あなたの下で絶えず変化します...実際に使用するには、多くの妄想的なものが必要ですこのリストの。)
public Set<Thread> findThreadsRunningClass(Class classToFindRunning) {
Set<Thread> runningThreads = new HashSet<Thread>();
String className = classToFindRunning.getName();
Map<Thread,StackTraceElement[]> stackTraces = Thread.getAllStackTraces();
for(Thread t : stackTraces.keySey()) {
StackTraceElement[] steArray = stackTraces.get(t);
for(int i = 0;i<steArray.size();i++) {
StackTraceElement ste = steArray[i];
if(ste.getClassName().equals(className)) {
runningThreads.add(t);
continue;
}
}
}
return runningThreads;
}
このアプローチが有効かどうか教えてください!
他のヒント
Javaプロファイラーは、JVMへのネイティブインターフェイスを使用します(JavaのJVMPI <!> lt; = 1.4.2または JVMTI for Java <!> gt; = 1.5.0 ))実行中のJavaアプリケーションからプロファイリング情報を取得します。
これは、 Sunが提供するネイティブコードプロファイラーがJVMにフックします。
JVM出口をブロックしているスレッドを見つけるために実行中のアプリケーションのクイックスタックトレースのみが必要な場合は、QUITシグナルを送信できます。
$ kill -QUIT <pid of java process>
Windowsでは、(java.exe
ではなくjavaw.exe
を使用して)コンソールウィンドウでアプリケーションを実行する必要があり、Ctrl-Pauseを押してスタックダンプを生成できます。どちらの場合も、<!>#8217;はstdoutに書き込まれます。
Visual VM を使用してJVMを監視します。たくさんの機能があります。試してみてください。
Javaスレッドダンプが必要だと思います。これにより、すべてのスレッドが現在実行している内容とともに一覧表示されます。私自身も同様の問題を抱えており、スレッドダンプが解決に役立ちました(Tomcatの終了時に終了しなかったQuartzスケジューラスレッド)。