当调用特定的Java方法时如何转储堆栈跟踪?
我们需要调试一个随机执行不应该执行的操作的 Java 应用程序。
为了了解问题的根本原因,我们需要在调用特定方法时获取堆栈跟踪。这听起来很简单(在这个特定方法中添加 Thread.dumpStack() ),但是这是来自 JDK 的代码类,因此我们真的不想弄乱它(即使我们确实可以) 。
有谁知道我们是否可以在 JVM 中实现某种“监听器”来检测何时调用特定方法并转储堆栈跟踪?
这是一个生产系统,因此如果解决方案是调试器,我们需要对性能影响非常有限的东西。
感谢您的意见。
We need to debug a Java application that randomly does stuff it should not do.
To understand the root cause of the issue, we would need to get a stacktrace whenever a specific method is called. This sounds easy (add Thread.dumpStack()
in this specific method), however this is a code class from the JDK, hence we do not really want to mess with it (even if we indeed could).
Does anybody know if we can implement some kind of "listener" in the JVM that would detect when a specific method is called and dump the stack trace?
This is a production system, so if the solution is a debugger we would need to have something that has very limited impact on performance.
Thank you for your input.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
使用字节曼。它可以很容易地将跟踪代码注入正在运行的服务器中。我们的支持团队喜欢它。 http://www.jboss.org/byteman
Use Byteman. It can inject tracing code into a running server pretty easily. Our support team love it. http://www.jboss.org/byteman
这些要求是矛盾的。无论你如何做,转储堆栈的代价都是昂贵的。 IMO,您真正需要做的是设置一个测试服务器并在那里进行调查。
FWIW,执行此类操作的最简单且可能最便宜的方法是将其中一个插入作为该方法的第一个语句:
These requirements are contradictory. Dumping the stack is expensive, no matter how you do it. IMO, what you really need to do is set up a test server and run your investigations there.
FWIW, the simplest and probably least expensive way to do this kind of thing is to insert one of these as the first statement of the method:
根据调用该方法的不同位置的不同,您可以在它周围放置一个包装器,并从包装器内进行堆栈转储。
Depending upon how many different locations the method is called from, you could put a wrapper around it and do a stack dump from within the wrapper.
为了简单起见,我所做的就是将以下行添加到我的代码中
Something I do for simplicity is add the following line to my code
使用 java.lang.reflect.Proxy 的实例代替相关类的实例。这允许您拦截所有方法调用并在将它们转发到实例之前执行某些操作。
我认为这是至少 1 个 AOP 框架的核心。
Instead of an instance of the Class in question, use an instance of
java.lang.reflect.Proxy
. This allows you to intercept all method calls and do something before forwarding them to the instance.I think this is the heart of at least 1 AOP framework.
使用
线程.currentThread().getStackTrace()
Use
Thread.currentThread().getStackTrace()
为此,我使用了 java Instrumentation api 。
使用 java Instrumentation api,您可以在运行时修改任何类字节码,并且可以添加一些代码(如 AOP)。我的 github 上有一个如何使用 javassist 在运行时检测 java 类和方法的示例。
https://github.com/kreyssel/maven-examples/tree/master/javaagent
您可以简单地修改 LoggerAgent.java 并删除日志记录语句并添加您的
Thread.dumpStack()
。在生产运行时中唯一需要更改的是将代理 jar 添加到 java 命令行。
您可以在此处阅读另一篇博客文章。
I used for this purpose the java instrumentation api.
With the java instrumentation api you can modify any class bytecode at runtime and you can add some code (like AOP). A example of how to instrument java classes and methods at runtime using javassist is on my github.
https://github.com/kreyssel/maven-examples/tree/master/javaagent
You can simply modify the LoggerAgent.java and remove the logging statements and add your
Thread.dumpStack()
.The only thing you change in your production runtime is to add the agent jar to the java command line.
Another blog post you can read here.