如何获取正在运行的应用程序的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 []传递给您的建议。