7

呼び出されるたびに何らかの方法Thread.interrupt()でログを記録し、どのスレッドが呼び出しを発行したか(およびその現在のスタック)をログに記録し、どのスレッドが中断されているかに関する情報を識別したいと思います。

これを行う方法はありますか?情報を検索していると、誰かがセキュリティマネージャを実装する可能性について言及しているのを見ました。これは実行時に実行できるものですか(たとえば、アプレットまたはWeb Startクライアントで)、またはこれを実行するためにインストールされたJVMをツールする必要がありますか?

それとも、これを行うためのより良い方法はありますか?

4

5 に答える 5

10

簡単なハックとして、これは私が思っていたよりもはるかに簡単でした。これは簡単なハックなので、配列を逆参照する前にスタックトレースが十分に深いことを確認するなどのことはしませんでした。署名されたアプレットのコンストラクターに、次のものを挿入しました。

log.info("Old security manager = " + System.getSecurityManager());
System.setSecurityManager(new SecurityManager() {
      @Override
      public void checkAccess(final Thread t) {
        StackTraceElement[] list = Thread.currentThread().getStackTrace();
        StackTraceElement element = list[3];
        if (element.getMethodName().equals("interrupt")) {
          log.info("CheckAccess to interrupt(Thread = " + t.getName() + ") - "
                   + element.getMethodName());
          dumpThreadStack(Thread.currentThread());
        }
        super.checkAccess(t);
      }
    });

方法は次のdumpThreadStackとおりです。

public static void dumpThreadStack(final Thread thread) {
  StringBuilder builder = new StringBuilder('\n');
  try {
    for (StackTraceElement element : thread.getStackTrace()) {
      builder.append(element.toString()).append('\n');
    }
  } catch (SecurityException e) { /* ignore */ }
  log.info(builder.toString());
}

もちろん、これを本番コードに残すことはできませんでしたが、どのスレッドが予期しない原因となっているのかを正確に教えてくれれば十分interrupt()でした。つまり、このコードを配置すると、への呼び出しごとにスタックダンプを取得しますThread.interrupt()

于 2009-04-28T20:19:19.503 に答える
4

ワイルドすぎることを試す前に、Javaデバッグ APIの使用を検討しましたか?Thread.interrupt()でMethodEntryEventsをキャプチャすることでそれができると思います。

ええと、それは古いインターフェースです。新しいJVMツール インターフェースもチェックアウトする必要があります。

于 2009-04-28T17:29:44.000 に答える
2

AspectJとそのメソッド呼び出しをラップする機能を見ていきます。メソッドの周りの実行ポイントカットがここで役立つはずです。interrupt()

(アプリケーションコードではなく)Javaシステムメソッド呼び出しをインターセプトしようとしているため、上記適切でない場合があることに注意してください。このスレッドはそれが可能であることを示唆しているようですが、彼が織りのrt.jarを作成したことに注意してください。

于 2009-04-28T17:31:09.707 に答える
1

他の人が言っているように...それが一度限りのことなら、JVMTIはおそらく最もハードコアな方法です。ただし、asmライブラリとインストルメンテーションAPIを使用して、Thread.interrupt()呼び出しの直前に作成した静的メソッドへの呼び出しを挿入する(またはThread.interrupt( )同じことをする方法、私はあなたがそれをすることができると思います)。

どちらも学ぶのに少し時間がかかりますが、一緒に作業するのはとても楽しいです。一度手に入れれば、将来的にはあらゆる種類の面白いことに使用できます:-)ここに貼り付けるのに適したスニペットは本当にありません。今のところ、ASMをグーグルで検索して、ASMのクリエイティブな使用法についてJIPを調べれば、インスピレーションが得られると思います。

JIP:Javaインタラクティブプロファイラー

于 2009-04-28T17:53:20.527 に答える
0

JMXでも試すことができます。

ManagementFactory.getThreadMXBean().getThreadInfo(aThreadID)

ThreadInfoオブジェクトを使用すると、ログに記録できます。

  • スレッドのスタックトレース
  • 名前、ステータスなどの一般的な有用な情報

編集

ライブスレッドIDのリストを取得するには、getAllThreadIds()を使用します。

long[] ids = ManagementFactory.getThreadMXBean().getAllThreadIds();
于 2009-04-28T17:39:53.833 に答える