Question

I am writing a short and simple profiler (in C), which is intended to print out stack traces for threads in various Java clients at regular intervals. I have to use the undocumented function AsyncGetCallTrace instead of GetStackTrace to minimize intrusion and allow for stack traces regardless of thread state. The source code for the function can be found here: http://download.java.net/openjdk/jdk6/promoted/b20/openjdk-6-src-b20-21_jun_2010.tar.gz in hotspot/src/share/vm/prims/forte.cpp. I found some man pages documenting JVMTI, signal handling, and timing, as well as a blog with details on how to set up the AsyncGetCallTrace call: http:// jeremymanson.blogspot.com/2007/05/profiling-with-jvmtijvmpi-sigprof-and.html.

What this blog is missing is the code to actually invoke the function within the signal handler (the author assumes the reader can do this on his/her own). I am asking for help in doing exactly this. I am not sure how and where to create the struct ASGCT_CallTrace (and the internal struct ASGCT_CallFrame), as defined in the aforementioned file forte.cpp. The struct ASGCT_CallTrace is one of the parameters passed to AsyncGetCallTrace, so I do need to create it, but I don't know how to obtain the correct values for its fields: JNIEnv *env_id, jint num_frames, and JVMPI_CallFrame frames. Furthermore, I do not know what the third parameter passed to AsyncGetCallTrace (void ucontext) is supposed to be?

The above problem is the main one I am having. However, other issues I am faced with include: [1] SIGPROF doesn't seem to be raised by the timer exactly at the specified intervals, but rather a bit less frequently. That is, if I set the timer to send a SIGPROF every second (1 sec, 0 usec), then in a 5 second run, I am getting fewer than 5 SIGPROF handler outputs (usually 1-3) [2] SIGPROF handler outputs do not appear at all during a Thread.sleep in the Java code. So, if a SIGPROF is to be sent every second, and I have Thread.sleep(5000);, I will not get any handler outputs during the execution of that code.

Any help would be appreciated. Additional details (as well as parts of code and sample outputs) will be posted upon request.

Thanks!

Was it helpful?

Solution

I finally got a positive result, but since little discussion was spawned here, my own answer will be brief.

The ASGCT_CallTrace structure (and the underlying ASGCT_CallFrame array) can simply be declared in the signal handler, thus existing only the stack: ASGCT_CallTrace trace; JNIEnv *env; global_VM_pointer->AttachCurrentThread((void **) &env, NULL); trace.env_id = env; trace.num_frames = 0; ASGCT_CallFrame storage[25]; trace.frames = storage;

The following gets the uContext: ucontext_t uContext; getcontext(&uContext);

And then the call is just: AsyncGetCallTrace(&trace, 25, &uContext);

I am sure there are some other nuances that I had to take care of in the process, but I did not really document them. I am not sure I can disclose the full current code I have, which successfully asynchronously requests for and obtains stack traces of any java program at fixed intervals. But if someone is interested in or stuck on the same problem, I am now able to help (I think).

On the other two issues: [1] If a thread is sleeping and a SIGPROF is generated, the thread handles that signal only after waking up. This is normal, since it is the thread's job to handle the signal. [2] The timer imperfections do not seem to appear anymore. Perhaps I mis-measured.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top