我正在开发非常庞大的基于 Java Web 的应用程序。由于在开发过程中没有进行适当的日志记录,因此我很难设置断点并调试应用程序,因为我不知道执行顺序。执行某些操作后,是否有任何机制可以获取正在运行的 java 应用程序的完整调用堆栈。
我在网上搜索了很长时间,但无法得出具体的解决方案。如果有什么适合的,请建议我。谢谢
方法 1:从命令行(JDK 发行版的一部分)使用 jstack 实用程序。
方法 2:向 java 进程发送信号 3,它将在 stdout 上转储堆栈跟踪。
方法 3:从应用程序内部调用 Thread.getAllStackTraces():
public class StackTraceDumper
{
public static dumpAllStackTraces ()
{
for (Map.Entry <Thread, StackTraceElement []> entry:
Thread.getAllStackTraces().entrySet ())
{
System.out.println (entry.getKey ().getName () + ":");
for (StackTraceElement element: entry.getValue ())
System.out.println ("\t" + element);
}
}
}
然后StackTraceDumper.dumpAllStackTraces()
在需要转储堆栈跟踪的地方使用。
Thread.dumpStack()
将当前线程的堆栈跟踪打印到标准错误流。
Thread.getAllStackTraces()
返回所有活动线程的堆栈跟踪映射。
Thread.getStackTrace()
返回表示此线程的堆栈转储的堆栈跟踪元素数组。
看看Throwable.getStackTrace()
。只需创建一个新的Throwable
;你实际上不必这样做throw
。
为什么不使用像 AspectJ 这样的 AOP 工具来捕获这些值并记录下来?您可以将 execution() 切入点与 after() 建议一起使用。对于非生产部署,您可以记录所有方法调用以及传递的值和返回值。对于生产环境来说,这将是太多的开销。为此,您可以将传递的值(在 AspectJ 建议中获得的 Object args[] )存储在局部变量中,并且仅在出现异常时记录它。但即使在这种情况下,也会有一些性能损失,因为原始值将被装箱以作为 Object[] 传递给您的建议。
有一些选项:
在您的代码中添加一些基本的日志记录:
new RuntimeException().printStackTrace();
这会将静态跟踪发送到 stderr
以防万一人们正在阅读这篇文章以了解如何获取当前线程堆栈的一个或多个类:
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
String smallStack = "Calling classes: " + System.lineSeparator() + stack[2] + System.lineSeparator() + stack[3];
这将获取当前线程的堆栈。
stack[0]
将是 getStackTrace 调用本身。stack[1]
将是您正在工作的代码行。stack[2]
如此。stack[3]