Answers:
如果只想跟踪当前线程(而不是像Ram的建议那样跟踪系统中的所有线程),请执行以下操作:
Thread.currentThread()。getStackTrace()
要查找呼叫者,请执行以下操作:
private String getCallingMethodName() {
StackTraceElement callingFrame = Thread.currentThread().getStackTrace()[4];
return callingFrame.getMethodName();
}
然后从需要知道其调用者是谁的方法中调用该方法。但是,请注意:列表中调用帧的索引可能会因JVM而异!这完全取决于在到达跟踪生成点之前,getStackTrace中有多少层调用。一个更健壮的解决方案是获取跟踪,并对其进行迭代以查找getCallingMethodName的框架,然后再进一步进行两步以找到真正的调用方。
您可以像这样获得堆栈跟踪:
Throwable t = new Throwable();
t.printStackTrace();
如果要访问框架,则可以使用t.getStackTrace()获取堆栈框架数组。
请注意,如果热点编译器一直在忙于优化操作,则此堆栈跟踪(就像其他任何堆栈跟踪一样)可能会丢失一些帧。
log.log(Level.SEVERE, "Failed to do something", new Throwable());
注意,Thread.dumpStack()实际上会引发异常:
new Exception("Stack trace").printStackTrace();
您还可以通过向该进程发送QUIT信号,向JVM发送信号以在运行的Java进程上执行Thread.getAllStackTraces()。
在Unix / Linux上使用:
kill -QUIT process_id
,其中process_id是Java程序的进程号。
在Windows上,您可以在应用程序中按Ctrl-Break,但除非运行控制台进程,否则通常不会看到此信息。
JDK6引入了另一个选项jstack命令,它将显示计算机上任何正在运行的JDK6进程的堆栈:
jstack [-l] <pid>
这些选项对于在生产环境中运行且无法轻松修改的应用程序非常有用。它们对于诊断运行时死锁或性能问题特别有用。
http://java.sun.com/developer/technicalArticles/Programming/Stacktrace/ http://java.sun.com/javase/6/docs/technotes/tools/share/jstack.html
Java 9引入了 StackWalker
用于堆栈栈和支持类。
以下是Javadoc的一些摘要:
该
walk
方法StackFrames
为当前线程打开的顺序流,然后应用给定的函数遍历该StackFrame
流。该流按顺序报告堆栈帧元素,从代表生成堆栈的执行点的最顶部的帧到最底部的帧。该StackFrame
流已关闭的步行方法返回时。如果尝试重用关闭的流,IllegalStateException
将抛出该错误。...
要快照当前线程的前10个堆栈帧,
List<StackFrame> stack = StackWalker.getInstance().walk(s -> s.limit(10).collect(Collectors.toList()));
您甚至不必在代码中执行此操作。您可以将Java HPROF附加到您的进程,然后随时按Control- \以输出堆转储,运行线程等。。。而不破坏您的应用程序代码。这有点过时了,Java 6带有GUI jconsole,但是我仍然发现HPROF非常有用。
如果您愿意输出到Rob Di Marco,答案是最好的stderr
。
如果您要捕获到String
,并按照常规跟踪添加新行,则可以执行以下操作:
Arrays.toString(Thread.currentThread().getStackTrace()).replace( ',', '\n' );