Reputation: 31
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.
Upvotes: 3
Views: 1461
Reputation: 687
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.
-javaagent:jarpath[=options]
Another blog post you can read here.
Upvotes: 0
Reputation: 31
Use Byteman. It can inject tracing code into a running server pretty easily. Our support team love it. http://www.jboss.org/byteman
Upvotes: 3
Reputation: 719679
"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."
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:
log.info("Method called", new Throwable());
new Throwable("method called").printStackTrace(System.out);
Upvotes: 1
Reputation: 12901
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.
Upvotes: 0
Reputation: 533880
Something I do for simplicity is add the following line to my code
log.info("Method called", new Throwable("HERE"));
Upvotes: 0
Reputation: 4597
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.
Upvotes: 0