如何找到所谓的线程

时间:2018-09-25 15:18:40

标签: java eclipse multithreading debugging

在Eclipse调试器中,我在堆栈中看到了对Thread.run的许多调用。这些步骤永远不会超越。我如何找出代码中的哪种方法启动了线程?右键单击不会提供任何有用的信息。据我所知,在Thread.class中的run方法上放置一个断点并检查Target并不能说明调用者是谁。

2 个答案:

答案 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();

}