これは珍しいことです:最初に現在実行中のスレッドを生成したクラス/メソッドを取得できますか?スタックトレースの実行は、当然のことながら、現在のスレッドの呼び出しスタックの最上部で停止します。現在のスレッドが生成されたクラスとメソッドの名前を取得できますか?
答えて
はい、できます: 私は2つの方法を提供します:1つの標準と1つのセミハック。
ほとんどの回答は、Javaの組み込み関数であると考えられていますが、外に出ています。
セキュリティマネージャをインストールしてSecurityManager.getThreadGroup()
を上書きすると、スタックトレースを簡単に取得できます。オプションで、残りのメソッドもオーバーライドすることで、セキュリティチェックの残りの部分を無効にすることもできます。
ハッキーワン:メインスレッド(mainという名前のメソッドとmain(String [] args)メソッド)でInheritableThreadLocalをインストールします。保護されているを上書きすると、完了です。
注:作成中のスレッドと親スレッド(参照)のスタックトレースは取得できますが、問題をトレースするのに十分なはずです。
私はそれがどれほど簡単かを示すために簡単なサンプルを書くことにしました: ここで結果を見ることができます。サンプルを見ると、私はこのサイトに投稿した最もエレガントなソリューションだと思います。ほとんどがb/cですが、それは明らかではありませんがシンプルでスマートです。
package bestsss.util;
import java.util.Arrays;
public class StackInterceptor extends InheritableThreadLocal<StackTraceElement[]>{
public static final StackInterceptor instance;
static{
instance = new StackInterceptor();
instance.set(new Throwable().getStackTrace());
}
@Override
protected StackTraceElement[] childValue(StackTraceElement[] parentValue) {
return new Throwable().getStackTrace();
}
//test//
public static void main(String[] args) {
Runnable r= new Runnable(){
@Override
public void run() {
System.out.printf("%s - creation stack: %s%n", Thread.currentThread(), Arrays.toString(instance.get()).replace(',', '\n'));
}
};
Thread t1 = new Thread(r, "t1");
//spacer
Thread t2 = new Thread(r, "t2");
t1.start();
t2.start();
}
}
Thread[t1,5,main] - creation stack: [bestsss.util.StackInterceptor.childValue(StackInterceptor.java:13) bestsss.util.StackInterceptor.childValue(StackInterceptor.java:1) java.lang.ThreadLocal$ThreadLocalMap.(ThreadLocal.java:334) java.lang.ThreadLocal$ThreadLocalMap.(ThreadLocal.java:242) java.lang.ThreadLocal.createInheritedMap(ThreadLocal.java:217) java.lang.Thread.init(Thread.java:362) java.lang.Thread.(Thread.java:488) bestsss.util.StackInterceptor.main(StackInterceptor.java:25)] Thread[t2,5,main] - creation stack: [bestsss.util.StackInterceptor.childValue(StackInterceptor.java:13) bestsss.util.StackInterceptor.childValue(StackInterceptor.java:1) java.lang.ThreadLocal$ThreadLocalMap.(ThreadLocal.java:334) java.lang.ThreadLocal$ThreadLocalMap.(ThreadLocal.java:242) java.lang.ThreadLocal.createInheritedMap(ThreadLocal.java:217) java.lang.Thread.init(Thread.java:362) java.lang.Thread.(Thread.java:488) bestsss.util.StackInterceptor.main(StackInterceptor.java:27)]
幸運と幸せなハッキング。
InheritableThreadLocalのソリューションは美しいものです。 main()のソースが利用できない場合(例えば、アプリケーションサーバの場合) –
main()は最初の(通常はermほぼ)メソッドですアプリケーションで呼び出すことができます。使用できない場合は、threadLocalを初期化した後、生成されたすべての子(およびグランド・チャイルド++)スレッドがトレース可能になります。要するに、できるだけ早くinit部分を行います。 – bestsss
通常、
スレッドの作成を制御できる場合は、スレッドをサブクラス化して、スタックトレースをコンストラクタに登録できます。もちろん、これはスレッドを作成したメソッドであり、必ずしも.start()
と呼ばれるものではありません。したがって、このメソッドをよりよくオーバーライドします。
しかし、多くの場合、どのメソッドがスレッドを開始したのではなく、実行者のにタスクをサブミットしたかを知りたいスレッドプールを使用します。
プールを制御する場合、threadFactoryを制御することは不思議ではないので、スレッドファクトリです。 – bestsss
@bestsss:はい。私の指摘は、このスレッドファクトリメソッドは通常、**あなたが本当に知りたい**ではないことです。誰が(どのメソッドを)スレッドプールに(または誰がその実行可能オブジェクトを作成して)送信したのかを知りたいでしょう。このために、スレッドプールはすべてのタスクにメタデータを追加する必要があり、何らかの方法でこれを取得する手段を提供します。 –
ŭlo、タスクを装飾するために 'AbstractExecutorService'に' newTaskFor(...) 'があります。逆に、第1のタスクがいつスレッドを生成したかを知ることは非常に重要である。理由は分かりませんが、新しく作成されたスレッドは親からかなり継承され、リークを防ぐために(ClassLoader、AccessControlContext、ThreadGroupなど)、徹底したThreadFactoryを使用します。 – bestsss
いいえ、不可能です。おそらく、これを達成する方法は、AspectJを使用してbefore
アドバイスをThread.start()
にすることです...もちろん、Thread
、パッチJDKコード(別のブートCLASSPATH)などをサブクラス化できますが、AspectJは最もポータブルでエレガントなソリューションです。
doh、それほど多くの作業:) – bestsss
- 1. AS3で現在のクラスとメソッドの名前を取得
- 2. 現在のクラスの名前を取得しますか?
- 3. 静的メソッドで現在のクラスの名前を取得するには?
- 4. Android DialogFragmentダイアログが作成されたクラスの名前を取得
- 5. 現在実行中のメソッドの名前を取得
- 6. 現在のユーザーの名前を取得
- 7. 現在のネットワークの名前を取得
- 8. dotnetコアで現在実行中のメソッドの名前を取得します。
- 9. 以前のインテント(メソッド)に使用されたスロット値を取得し、現在のメソッドで使用しますか?
- 10. ロガーの現在の名前空間、クラス名、メソッド名の取得を最適化する方法
- 11. 次のdivを現在のクラス名と同じクラス名で取得する
- 12. 事前バインドされたHibernateセッションを取得できませんでした - 現在のスレッドのトランザクション同期セッションを取得できませんでした
- 13. フィルタの前に発生する現在のアクションを取得できますか?
- 14. Delphi 7で現在のメソッドの名前を取得する方法は?
- 15. VB.netで変数名の型と現在のクラスまたはメソッドの値を取得する方法は?
- 16. Android.Gradle:プログラムで現在のモジュール名を取得できますか?
- 17. アクティビティワークフローの現在と前のタスク名を取得する方法
- 18. Java - getメソッドが呼び出されたときにクラス属性名を取得
- 19. コマンドラインからHerokuから現在のデータベースの名前を取得
- 20. 現在のコンテキストに名前が存在しません同じクラスでエラーが発生しました
- 21. "現在のスレッドのトランザクション同期セッションを取得できませんでした"
- 22. 現在のメソッドは、どのメソッドが呼び出されたかを知ることができますか?
- 23. SSRS! - 。現在のアイテム(テキストボックスまたは列)のReportItem ____名前を取得します
- 24. clojureでは、どのようにして現在の名前空間のファイル名を取得できますか?
- 25. ネストされたクラスの中から周囲のクラスの名前を取得
- 26. メソッドが定義されたクラスを取得しますか?
- 27. Xposedログの現在のメソッド名を使用できますか?
- 28. 現在のメソッドの名前を取得するためにnameofを使用しています
- 29. 次のコードを作成すると、現在の月と前の12ヶ月が生成されます。
- 30. UIPanGestureRecognizerメソッドで現在のタッチポイントと以前のタッチポイントを取得する方法は?
私はあなたが何か重要なものではなく、いくつかのハッキングデバッグのためにこれをやってくれることを願っています。 –
ハハ、あなたは正しく仮定します。 --D – Wilco
関連していますが(同じではありません):[Javaでスタックトレースを作成する](http://stackoverflow.com/questions/6270256/forging-a-)-私はこのパスを開始してから私の鼻を止めていません。 stack-trace-in-java) –