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

时间:2013-02-05 10:35:14

标签: java debugging callstack

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

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

6 个答案:

答案 0 :(得分:18)

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

方法2:将信号3发送到java进程,它将在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()

答案 1 :(得分:6)

Thread.dumpStack()           将当前线程的堆栈跟踪打印到标准错误流。 Thread.getAllStackTraces()           返回所有活动线程的堆栈跟踪映射。 Thread.getStackTrace()           返回表示此线程的堆栈转储的堆栈跟踪元素数组。

答案 2 :(得分:5)

看看Throwable.getStackTrace()。只需创建一个新的Throwable;你实际上不需要throw它。

答案 3 :(得分:3)

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

您可以通过

以编程方式执行此操作
Map<Thread, StackTraceElement[]> m = Thread.getAllStackTraces();

这里有关于获取和分析堆栈跟踪的more info

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

答案 4 :(得分:0)

有一些选择:

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

为您的代码添加一些基本日志记录:

new RuntimeException().printStackTrace();

这会使静态跟踪到stderr

答案 5 :(得分:0)

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