有没有一种方法可以使用JVMTI生成周期性java线程转储?

有没有一种方法可以使用JVMTI生成周期性java线程转储?,java,jvmti,thread-dump,Java,Jvmti,Thread Dump,java中有多种生成线程转储的方法 我想使用(C API)来生成它,以便评估它对正在运行的JVM的性能影响。(我知道jstack和JMX;这个问题通常不是关于获取线程转储,而是关于使用JVMTIAPI) 我的代码是基于。在那里,java代理附加到SIGQUIT信号。我希望避免这种情况,因为这与JVM向stdout写入线程转储时使用的信号相同。我想避免那种口是心非的行为 换句话说,我想附加一个不同的信号,或者找到一种方法让代理定期生成线程转储 在那里,java代理附加到SIGQUIT信号。我希望避

java中有多种生成线程转储的方法

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

我的代码是基于。在那里,java代理附加到SIGQUIT信号。我希望避免这种情况,因为这与JVM向stdout写入线程转储时使用的信号相同。我想避免那种口是心非的行为

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

在那里,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);
我想附加一个不同的信号

这篇论文虽然有点旧,但信息应该仍然相关

只是一个如何进行信号处理的示例

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");
当然,您可以编写完全本地的信号处理程序(请注意,我还没有测试它,这只是一个应该可以工作的想法)

或者找到一种方法让代理定期生成线程转储

在您的样本中有global*gdata

typedef struct {
   /* JVMTI Environment */
   jvmtiEnv      *jvmti;
   jboolean       vm_is_started;
   /* Data access Lock */
   jrawMonitorID  lock;
} GlobalAgentData;

static GlobalAgentData *gdata;

。。。因此,只要随时从那里获取jvmtiEnv(计时器回调等)

jvmtiEventCallbacks中的事件看起来都不合适(除非您想使用DataDumpRequestion,但如果您想使用,您就不会在这里问:好的,到目前为止,这就是我连接到jvm的方式(略有不同)因此,我想这就引出了下一个问题:如果不是从回调调用GetStackTrace,我如何获取指向jvmtiEnv的指针以调用GetStackTrace?关键是调用t

如果您的目标是定期收集线程转储,您可以使用Java Flight Recorder,这是


从发布Oracle JDK 7 Update 40(7u40)开始,Java任务控制与HotSpot JVM捆绑在一起。

您引用的博客条目包含了JVMTI管道的大部分需要。您可以使用gdata中的JVMTIenv。这是合法的。请确保您正在进行JNI调用,以便为当前线程提供适当的JNIenv

现在,您需要添加一种方法来获得通知以执行您的操作(例如:线程转储)。启动一个线程,该线程侦听套接字、使用、命名信号量等,这是您可以从外部戳到的


然后,您可以根据需要从事件处理程序循环中调用dumpThreadInfo()。

jvmtiEventCallbacks中的所有事件看起来都不合适(除非您想使用DataDumpRequestion,但如果使用了,您就不会在这里问:)。看起来你最好让你的代理直接呼叫
GetStackTrace
。有什么原因你不能这样做吗?@Paul Hicks,你能发布一个链接或代码,说明在这种情况下我将如何连接到jvm吗?你可以将代理dll或.so放在jvm的-agentpath中,或者将其定义为-agentlib。看一看或看一看。这是你想知道的吗?我应该把这变成一个答案吗?好的,这就是我到目前为止连接到jvm的方式(有一些细微的区别)。所以我想这就引出了下一个问题:如果不是从回调调用GetStackTrace,如何获取指向jvmtiEnv的指针?关键是要定期调用该函数。从
*gdata
获取
*jvmti
安全吗?我不太确定,但我可以试试。应该是安全的。至少你总是可以使用和和gdata->lock,但是我认为在你同时访问gdata->jvmti之前,没有必要这样做。线程的第一个参数接受jvmtiEnv。因此,您可以从本机创建的线程中定期转储线程。使用*jvmti是100%安全的。生命周期被指定为直到代理卸载为止。我还建议不要使用信号——JVM内部有很多信号,信号链接很难正确。找到一种不同的触发机制(就像我的答案所建议的那样)-例如:套接字、信号量等。。。
typedef struct {
   /* JVMTI Environment */
   jvmtiEnv      *jvmti;
   jboolean       vm_is_started;
   /* Data access Lock */
   jrawMonitorID  lock;
} GlobalAgentData;

static GlobalAgentData *gdata;