这是一个不寻常的问题:是否有可能获得最初产生当前正在运行的线程的类/方法?运行堆栈跟踪将自然停在当前线程的调用堆栈顶部。
答案 0 :(得分:7)
是的,您可以: 我为您提供两种方式:一种是标准方式,一种是半方式。
大多数答案都过分了,而它应该是Java中的内置函数。
安装安全管理器并覆盖SecurityManager.getThreadGroup()
,您可以轻松获得堆栈跟踪,也可以通过覆盖其余方法来禁用其余的安全检查。
Hacky one:在主线程中安装一个InheritableThreadLocal(名为main的那个并由方法main(String [] args)运行)。覆盖受保护的InheritableThreadLocal.childValue(T parentValue)
,您就完成了。
注意:您将获得正在创建的线程的堆栈跟踪和父线程(引用),但这应该足以跟踪问题。
我决定编写超级简单的样本来说明它是多么容易: 在这里你可以看到结果。看一下这个样本,我想这是我在这个网站上发布过的最优雅的解决方案,主要是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)]
祝你好运和快乐的黑客攻击。
答案 1 :(得分:1)
通常,没有。
如果您可以控制线程创建,则可以继承Thread并在构造函数中注册堆栈跟踪。当然,这是创建线程的方法,不一定是调用.start()
的线程。因此,更好地覆盖这种方法。
但是通常你会使用线程池,在那里你想知道哪个方法将任务提交给执行者的execute()
,而不是哪个方法启动了线程。
答案 2 :(得分:0)
可以通过产生对象的合作 - 它可以将信息写入Thread对象(例如,如果你想要一个hacky方式,可以写入线程的名称,或者你可以为此目的创建一个字段),你可以后来用于调试等。但我不认为有任何'内置'方式来获取此信息。
答案 3 :(得分:0)
不,这是不可能的。实现这一点的方法可能是使用AspectJ在before
上提供Thread.start()
建议...当然,您可以继承Thread
,修补JDK代码(不同的引导CLASSPATH)等,但AspectJ似乎是最便携和优雅的解决方案。