Monitoring Java from within Java
I want to write a simple visualization of a Java program by displaying the program's method calls as开发者_Go百科 branches of a tree. This could be done quite simply by having the program itself tell the visualization what it is doing, but I want to be able to do this with any Java method/class and not just the ones I modify to do so.
What I need is the ability to watch the methods a program calls and what methods are called within that method and so on. Obviously, stack traces provide exactly this functionality:
java.lang.NullPointerException
at MyClass.mash(MyClass.java:9)
at MyClass.crunch(MyClass.java:6)
at MyClass.main(MyClass.java:3)
So I thought about having the program I want to monitor run in a thread and then just look at that thread's stack. However, the thread class does not really support this. It only supports printing the current stack.
Now I, of course, thought of simply changing the PrintStream of the System class so the thread would print its stack into my PrintStream, but this feels kind of wrong.
Is there a better way to do this? Are there any pre-existing classes/methods I can use?
Also, I'm currently downloading the Java source code, to check how exactly the thread class prints its stack so I could maybe subclass thread and imitate the dumpStack() method with my own getStack() method.
Look also at VisualVM, shipped with latest Java releases.
Oh shoot, looking through the source code I noticed the thread class has a method public StackTraceElement[] getStackTrace(), it just wasn't in the documentation I was reading. Now I feel dumb.
So yeah, that seems to be the solution.
One approach might be to use something like BCEL to preprocess the target bytecode to insert calls to your own code on every method entry and exit (probably best to do exit by wrapping the whole method in a try/finally block, to catch exception exits). From this, you can deduce the call tree exactly as it happens.
You could use AspectJ for that. Have a look at this description of exactly your use case.
Have a look at the ThreadMXBean class -- it my provide what you need. Essentially, you:
- call ManagementFactory.getThreadMXBean() to get an instance of ThreadMXBean;
- call getAllThreadIds() on the resulting ThreadMXBean to enumerate current threads;
- call getThreadInfo() to get the top n stack trace elements from a given list of threads.
精彩评论