There are multiple ways to generate thread dumps in java.
I'd like to use JVMTI (the C API) to generate it, in order to evaluate its performance impact on a running JVM. (I am aware of jstack and JMX ; this question is not generally about getting thread dumps, but about using the JVMTI API).
I'm basing my code off of this blog post. In there, the java agent attaches to the SIGQUIT signal. I'd like to avoid that, because that is the same signal that the JVM uses in order to write a thread dump to stdout. I want to avoid that duplicity.
In other words, I'd like to either attach to a different signal, or find a way for the agent to generate a thread dump periodically.
In there, the java agent attaches to the SIGQUIT signal. I'd like to avoid that, because that is the same signal that the JVM uses in order to write a thread dump to stdout. I want to avoid that duplicity.
Just remove the following snippet from your code
/* Set callbacks and enable event notifications */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.DataDumpRequest = &dumpThreadInfo;
err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));
CHECK_JVMTI_ERROR(jvmti, err);
err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,JVMTI_EVENT_DATA_DUMP_REQUEST, NULL);
CHECK_JVMTI_ERROR(jvmti, err);
I'd like to either attach to a different signal
Here is the paper, that is a bit old, but the information should be still relevant.
Just a sample of how to do a signal handling
import sun.misc.Signal;
import sun.misc.SignalHandler;
public class ThreadDumpSignalHandler implements SignalHandler {
private volatile SignalHandler old;
private ThreadDumpSignalHandler() {
}
public static void register(String sigName) {
ThreadDumpSignalHandler h = new ThreadDumpSignalHandler();
h.old = Signal.handle(new Signal(sigName), h)
}
public void handle(Signal sig) {
threadDump();
if(old != null && old != SIG_DFL && old != SIG_IGN) {
old.handle(sig);
}
}
// call your own threadDump native method.
// note that in the implementation of this method you are able to access jvmtiEnv from *gdata (see below)
private native void threadDump();
}
ThreadDumpSignalHandler.register("INT");
Of cause you can write completely native signal handler (please note that I haven't tested it, this is just an idea that should work)
static sighandler_t old_handler;
static void thread_dump_handler(int signum) {
if(gdata && gdata->jvmti) {
... get thread dump
}
if(old_handler) {
old_handler(signum);
}
}
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) {
old_handler = signal(SIGINT, thread_dump_handler);
...
}
or find a way for the agent to generate a thread dump periodically.
In your sample there is global *gdata
typedef struct {
/* JVMTI Environment */
jvmtiEnv *jvmti;
jboolean vm_is_started;
/* Data access Lock */
jrawMonitorID lock;
} GlobalAgentData;
static GlobalAgentData *gdata;
... so, just obtain jvmtiEnv from there at any time you want (timer callbacks, etc.)
If your goal is to periodically collect thread dump, you can use Java Flight Recorder, that is part of Java Mission Controller
Starting with the release of Oracle JDK 7 Update 40 (7u40), Java Mission Control is bundled with the HotSpot JVM.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With