如何在调用特定Java方法时转储堆栈跟踪?

时间:2011-03-11 13:18:12

标签: java debugging stack-trace

我们需要调试一个随机执行它不应该做的事情的Java应用程序。

要了解问题的根本原因,我们需要在调用特定方法时获取堆栈跟踪。这听起来很简单(在这个特定方法中添加Thread.dumpStack()),但这是JDK的代码类,因此我们并不想搞砸它(即使我们确实可以)。

有人知道我们是否可以在JVM中实现某种“侦听器”,它会检测何时调用特定方法并转储堆栈跟踪?

这是一个生产系统,因此如果解决方案是调试器,我们需要对性能产生非常有限的影响。

感谢您的投入。

7 个答案:

答案 0 :(得分:3)

使用Byteman。它可以很容易地将跟踪代码注入到正在运行的服务器中。我们的支持团队喜欢它。 http://www.jboss.org/byteman

答案 1 :(得分:1)

  

“有人知道我们是否可以在JVM中实现某种”侦听​​器“,它会检测何时调用特定方法并转储堆栈跟踪?

     

这是一个生产系统,因此如果解决方案是调试器,我们需要对性能产生非常有限的影响。“

这些要求是矛盾的。无论你怎么做,倾倒堆栈都很昂贵。 IMO,你真正需要做的是建立一个测试服务器并在那里进行调查。

FWIW,执行此类操作的最简单且可能最便宜的方法是插入其中一个作为方法的第一个语句:

    log.info("Method called", new Throwable());

    new Throwable("method called").printStackTrace(System.out);

答案 2 :(得分:0)

根据调用方法的位置数量,您可以在其周围放置一个包装器并从包装器中执行堆栈转储。

答案 3 :(得分:0)

我为简单起见做了一些事情,将以下行添加到我的代码中

log.info("Method called", new Throwable("HERE"));

答案 4 :(得分:0)

使用java.lang.reflect.Proxy的实例,而不是相关类的实例。这允许您拦截所有方法调用并在将它们转发到实例之前执行某些操作。

我认为这是至少1个AOP框架的核心。

答案 5 :(得分:0)

答案 6 :(得分:0)

我为此目的使用了java instrumentation api

使用java instrumentation api,您可以在运行时修改任何类字节码,并且可以添加一些代码(如AOP)。如何使用javassist在运行时检测java类和方法的示例在我的github上。

https://github.com/kreyssel/maven-examples/tree/master/javaagent

您只需修改LoggerAgent.java并删除日志记录语句并添加Thread.dumpStack()

您在生产运行时中唯一更改的是将代理jar添加到java命令行。

-javaagent:jarpath[=options]

您可以阅读另一篇博客文章here