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