【问题标题】:How to get Java Call Stack of a running application如何获取正在运行的应用程序的 Java 调用堆栈
【发布时间】:2013-01-20 06:10:08
【问题描述】:

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

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

【问题讨论】:

标签: java debugging callstack


【解决方案1】:

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

方法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()

【讨论】:

  • 你能建议我在哪里写这个stackTrace()代码sn-p吗?我想写一个可以随处使用的单一代码sn-p。
  • jstack 不作为 JRE 的一部分提供(至少在版本 7 中没有),但它作为 JDK 的一部分提供。
【解决方案2】:

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

【讨论】:

  • 你能建议我在哪里写这个stackTrace()代码sn-p吗?我想写一个可以随处使用的单一代码sn-p
【解决方案3】:

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

【讨论】:

  • 这将只转储一个线程的堆栈跟踪,即当前线程。
【解决方案4】:

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

您可以通过

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

这是获取和分析堆栈跟踪的more info

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

【讨论】:

  • 当我从应用程序按钮执行某些操作时,我想找到完整的调用堆栈,例如(关于注册患者)。你知道 BTrace 它是什么吗:(???
  • 除了向您推荐一个 SO 答案(见上文)之外,我真的无法给出建议
  • 你能建议我在哪里写这个stackTrace()代码sn-p吗?我想写一个可以在任何地方使用的单一代码sn-p。
【解决方案5】:

有一些选择:

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

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

new RuntimeException().printStackTrace();

这会将静态跟踪发送到标准错误

【讨论】:

  • 这将只打印一个线程的堆栈跟踪,即当前线程。
  • 是的,代码行打印当前线程。其他示例将打印所有线程堆栈。
【解决方案6】:

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

【讨论】:

    【解决方案7】:

    以防万一人们正在阅读这篇文章以了解如何获取当前线程堆栈的一个或多个类:

    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] 是第一个“有趣”的堆栈元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-04
      • 2022-01-17
      • 2012-05-12
      • 1970-01-01
      • 1970-01-01
      • 2010-09-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多