有多种方法可以在Java中生成线程转储。

我想使用JVMTI(C API)来生成它,以便评估其对正在运行的JVM的性能影响。 (我知道jstack和JMX;这个问题通常不是关于获取线程转储的问题,而是关于使用JVMTI API的问题)。

我基于this blog post建立我的代码。在那里,java代理附加到SIGQUIT信号。我想避免这种情况,因为这与JVM用于将线程转储写入stdout的信号相同。我想避免这种重复。

换句话说,我想附加到一个不同的信号,或者为代理找到一种定期生成线程转储的方法。

最佳答案



只需从代码中删除以下代码段

/* 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);



Here is纸张,该纸张有些旧,但信息仍应相关。

只是如何进行信号处理的样本
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");

当然,您可以编写完全 native 的信号处理程序(请注意,我尚未对其进行测试,这只是一个可行的想法)
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);

    ...
}



您的样本中有全局 * gdata
typedef struct {
   /* JVMTI Environment */
   jvmtiEnv      *jvmti;
   jboolean       vm_is_started;
   /* Data access Lock */
   jrawMonitorID  lock;
} GlobalAgentData;

static GlobalAgentData *gdata;

...因此,您可以随时从那里获取jvmtiEnv(计时器回调等)。

关于java - 有没有一种方法可以使用JVMTI生成定期的Java线程转储?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26795511/

10-10 06:13