如何获取正在运行的应用程序的Java Call Stack

我正在研究非常庞大的基于Java web的应用程序。 由于在开发过程中没有进行适当的日志记录,因此我很难设置断点并调试应用程序,因为我不知道执行顺序。 在执行某些操作后,是否有任何机制可以获取正在运行的java应用程序的完整调用堆栈。

我在网上搜索了很长时间,但无法找到具体的解决方案。 如果有什么东西,请建议我。 谢谢

方法1:从命令行使用jstack实用程序(JDK发行版的一部分)。

方法2:将信号3发送到java进程,它将在stdout上转储堆栈跟踪。

方法3:从应用程序中调用Thread.getAllStackTraces():

public class StackTraceDumper { public static dumpAllStackTraces () { for (Map.Entry  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它。

您可以通过按Ctrl + Break或发送信号3(在基于Unix的系统上)触发堆栈转储。 请注意,您将获得每个线程的堆栈跟踪。 这将转到标准错误 ,因此请确保您的日志记录正在捕获此信息。

您可以通过编程方式执行此操作

 Map m = Thread.getAllStackTraces(); 

以下是有关获取和分析堆栈跟踪的更多信息 。

正如您所指出的,BTrace是另一种可能性。 这是使用它的SO答案 。

有一些选择:

  • 在调试器中运行它,并暂停所有线程,然后您可以检查它们
  • 使用VisualVM连接到正在运行的进程并触发线程转储。 它配备了JDK。
  • 在命令行上使用jstack来转储线程。

在代码中添加一些基本日志记录:

 new RuntimeException().printStackTrace(); 

这将为stderr带来静态痕迹

为什么不使用像AspectJ这样的AOP工具来捕获这些值并记录? 您可以使用execution()切点和after()建议。 对于非生产部署,您可以记录所有方法调用以及传递的值和返回的值。 对于生产环境来说,这将是太多的开销。 为此,您可以在局部变量中存储传递的值(在AspectJ建议中获得的对象args []),并且只在exception情况下记录它。 但即使在这种情况下也会有一些性能损失,因为原始值将被装箱以作为Object []传递给您的建议。