我可以获取生成当前线程的类和方法的名称吗?
这是一个不寻常的问题:是否有可能获得最初产生当前运行的线程的类/方法? 运行堆栈跟踪将自然停在当前线程的调用堆栈顶部。
是的,你可以:我为你提供两种方式:一种标准,一种半黑客。
大多数答案都是过分的,而它应该是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{ 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(); } }
线程[t1,5,main] - 创建堆栈:[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)] 线程[t2,5,main] - 创建堆栈:[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)]
祝你好运和快乐的黑客。
通常,没有。
如果您可以控制线程创建,则可以inheritanceThread并在构造函数中注册堆栈跟踪。 当然,这是创建线程的方法,不一定是调用.start()
。 因此,更好地覆盖此方法。
但是通常你会使用线程池,你想知道哪个方法将任务提交给执行者的execute()
,而不是哪个方法启动了线程。
不,这是不可能的。 可能实现这一点的方法是before
使用AspectJ对Thread.start()
进行建议…当然你可以inheritanceThread
,修补JDK代码(不同的引导CLASSPATH)等,但是AspectJ似乎是最便携的优雅的解决方案。
产生对象的合作是可能的 – 它可以将信息写入Thread对象(例如,如果你想要一个hacky方式进入线程的名称,或者你可以为此目的创建一个字段),你可以在以后使用它调试等但我不认为有任何“内置”方式来获取此信息。