簡體   English   中英

有沒有一種方法可以使用JVMTI生成定期的Java線程轉儲?

[英]Is there a way to generate a periodic java thread dump using JVMTI?

在Java中有多種生成線程轉儲的方法。

我想使用JVMTI (C API)生成它,以便評估其對運行中的JVM的性能影響。 (我知道jstack和JMX;這個問題通常不是關於獲取線程轉儲,而是關於使用JVMTI API)。

我的代碼基於此博客文章 在這里,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");

當然,您可以編寫完全本機的信號處理程序(請注意,我尚未對其進行測試,這只是一個可行的想法)

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 Flight Recorder,它是Java Mission Controller的一部分

從Oracle JDK 7 Update 40(7u40)發行版開始,Java Mission Control與HotSpot JVM捆綁在一起。

您引用的博客條目具有JVMTI管道所需的大部分功能。 您可以從gdata使用JVMTIenv。 那是合法的。 確保是否要進行JNI調用以為當前線程使用適當的JNIenv。

現在,您需要添加一種方法來獲取通知以采取措施(例如:線程轉儲)。 旋轉一個偵聽套接字,使用inotify ,名為semaphores等的線程。-您可以從外面戳一下。

然后,您可以根據需要從事件處理程序循環中調用dumpThreadInfo()。

jvmtiEventCallbacks中的所有事件都不適合(除非您想使用DataDumpRequestion,但是如果您這樣做了,您將不會在這里詢問:ok,所以到目前為止,這幾乎就是我附加到jvm的方式(有細微差別)因此,我想這引出了下一個問題:如果不是從回調中調用GetStackTrace,如何獲取指向jvmtiEnv的指針呢?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM