2009-04-28 6 views
6

Thread.interrupt()が呼び出されるたびに、どのスレッドが呼び出し(およびその現在のスタック)を発行したかを記録し、どのスレッドが中断しているかの情報を特定するたびにログを記録したいと思います。スレッド割り込みごとにログを記録する方法はありますか?

これを行う方法はありますか?情報を検索すると、誰かがセキュリティマネージャを実装する可能性を参照していることがわかりました。これは実行時に(アプレットやWeb Startクライアントなどで)実行できるものか、インストール済みのJVMをツールとして使用する必要がありますか?

これを行うには良い方法がありますか?

+0

さまざまな複雑さとパフォーマンスのヒットでいくつかの方法を考えることができます。バグを発見するのは一度だけですか、それともあなたがプロダクションで望むものなのでしょうか? – Fredrik

+0

これは主に私が一度限りのものとして欲しいものですが、私が随時使用したいと思うものです。それが充分フレンドリーだったら、私はプロダクションコードにしておきますが、必要に応じてリモートデバッグ(ログ経由)の追加モードを無効にします。 – Eddie

答えて

9

、これは私はそれが可能だろうと思ったよりも行うことがたくさん簡単でした。このクイックハックですが、私はなど、スタックトレースは、配列を参照解除する前に十分な深さであることを保証するようなことをしなかったので、私は私の署名付きアプレットのコンストラクタに次のように挿入:

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()への呼び出しごとにスタックダンプを取得します。

+1

Javaのいくつかのバージョンでは、SecurityManagerはcheckPermissionメソッドをオーバーライドして(もっとも許容され、最も単純なオプションを返すだけです)、そうでないとjava.security.AccessControlException:access deniedのようなセキュリティエラーが発生する可能性があります。 – vazor

4

あまりにも野生のものを試す前に、Java debuggingAPIを使用したことがありますか?私は、Thread.interrupt()でMethodEntryEventsをキャプチャしていると思います。

Eeek、これは古いインターフェイスです。新しいJVM ToolInterfaceも確認してください。

+0

私はJavaデバッグAPIを漠然と認識していますが、私が使用するアプリケーション内でどのように使用するのかはわかりません。 – Eddie

+0

私は今あなたにいくつかのリンクを与えました。短い答えは、JVM呼び出しにフラグを追加してから、外部的にJVMに接続できることです。 –

+0

残念ながら、あなたの提案は私を助けません。新しいJVMツールインターフェイスにはJNIが必要で、古いJavaデバッグAPIはアプレットでは使用できません。しかし、この情報は、今後何か他のものに役立つことがあります。ポインタをありがとう。 – Eddie

2

私はAspectJとそのメソッド呼び出しをラップする機能を調べます。 interrupt()メソッドの周りのexecution pointcutメソッドがここで役立ちます。

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

+0

JVMライブラリでメソッドをラップすることもできますか? – Eddie

+0

それは良い点です、私がタイプしたのと同じように検討していました。さまざまなバイトウィービングのメカニズムがありますが(コンパイル時/実行時/クラスロード時)、これらのうちの1つが機能する可能性があります。 –

0

あなたはJMXでも試みることができる:

ManagementFactory.getThreadMXBean().getThreadInfo(aThreadID) 

ThreadInfoオブジェクトにあなたがログインすることができます:

  • スレッドのスタックトレース名、状態、などのような
  • 一般userful情報

ライブスレッドIDのリストを得るためにEDIT

使用getAllThreadIds():それはJVMTIはおそらく1回限りのものであれば他の人として

long[] ids = ManagementFactory.getThreadMXBean().getAllThreadIds(); 
+0

割り込みコールをキャッチする方法はどうですか? – Fredrik

+0

別の方法(JVM計測、デバッグフック、AOPなど)を使用していますか? – dfa

1

が...言いましたほとんどのハードコアの方法を行く。ただし、asmライブラリとinstrumentation APIを使用して、Thread.interrupt()コールの直前に作成した静的メソッドへの呼び出しを挿入するエージェントを作成することもできます(またはThread.interrupt( )メソッドは、同じことを行うには、私はあなたがそれを行うことができると思う)。

どちらも学習に時間がかかりますが、これは非常に楽しく、一度それを保持すると、将来的にあらゆる種類の面白いことに使用できます:-) 私は本当に何も持っていません今すぐここに貼り付けるのが良いスニペットですが、ASMのためにgoogleをして、ASMのいくつかの創造的な使用のためにJIPを見ていればインスピレーションを感じるでしょう。

JIP:迅速なハックとしてJava Interactive Profiler

+0

あなたはhttp://asm.ow2.org/を参照していると思いますか?とても創造的ですね!私は調査する時間がありませんでしたが、これは将来的に私を良くする何かのように見えます。ありがとう。 – Eddie

+0

URLを含めないと申し訳ありません。 – Fredrik

関連する問題