在Eclipse调试器中,我在堆栈中看到了对Thread.run的许多调用。这些步骤永远不会超越。我如何找出代码中的哪种方法启动了线程?右键单击不会提供任何有用的信息。据我所知,在Thread.class中的run方法上放置一个断点并检查Target并不能说明调用者是谁。
答案 0 :(得分:1)
在方法java.lang.Thread.start()
上设置一个断点,以找出线程在哪里启动。
答案 1 :(得分:1)
如果您可以控制线程的创建(即,在代码中调用new Thread()或提供自己的ThreadFactory),则可以创建自己的Thread子类,并使用该子类“注入”调用创建线程时调用-stack,并将start()
调用到将要在栈中的变量中。例如:
public static class KnowledgeableThread extends Thread {
private static class KnowledgeableRunnable implements Runnable {
StackTraceElement[] stackTraceAtInit;
StackTraceElement[] stackTraceAtStart;
private final Runnable actualRunnable;
KnowledgeableRunnable(Runnable actualRunnable){
this.actualRunnable = actualRunnable;
this.stackTraceAtInit = Thread.currentThread().getStackTrace();
}
@Override
public void run() {
actualRunnable.run();
}
}
public KnowledgeableThread(Runnable target, String name) {
super(new KnowledgeableRunnable(target), name);
}
@Override
public synchronized void start() {
try {
Field[] fields = Thread.class.getDeclaredFields();
for(Field f : fields){
if(f.getName().equals("target")){
f.setAccessible(true);
KnowledgeableRunnable knowledgeableRunnable = (KnowledgeableRunnable)f.get(this);
knowledgeableRunnable.stackTraceAtStart = Thread.currentThread().getStackTrace();
}
}
super.start();
} catch (IllegalAccessException e){
throw new IllegalStateException(e);
}
}
}
如果您在actualRunnable.run()
的断点“内部”(例如下面的代码中的println
)处停止,并检查属于KnowledgeableRunnable.run()
的堆栈帧中的变量,则您应该可以访问两个堆栈跟踪。
public static void a(Thread kt){
b(kt);
}
public static void b(Thread kt){
c(kt);
}
public static void c(Thread kt){
kt.start();
}
public static void main(String[] args) throws InterruptedException {
Thread kt = new KnowledgeableThread(new Runnable() {
@Override
public void run() {
System.out.println("Hello Foo-Bar");
}
}, "my-thread");
a(kt);
kt.join();
}