8

Java でスレッド ダンプを生成する方法は複数あります。

実行中の JVM に対するパフォーマンスの影響を評価するために、JVMTI (C API) を使用して生成したいと考えています。(私は jstack と JMX を認識しています。この質問は一般にスレッド ダンプの取得に関するものではなく、JVMTI API の使用に関するものです)。

このブログ投稿からコードを作成しています。そこでは、Java エージェントが SIGQUIT シグナルにアタッチされます。これは、JVM がスレッド ダンプを stdout に書き込むために使用する信号と同じであるため、避けたいと思います。その二面性は避けたい。

つまり、別のシグナルにアタッチするか、エージェントが定期的にスレッド ダンプを生成する方法を見つけたいと考えています。

4

4 に答える 4

2

定期的にスレッド ダンプを収集することが目的の場合は、 Java Mission Controllerの一部である Java Flight Recorder を使用できます。

Oracle JDK 7 Update 40 (7u40) のリリース以降、Java Mission Control は HotSpot JVM にバンドルされています。

于 2014-11-17T01:31:04.330 に答える
2

そこでは、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 を取得するだけです (タイマー コールバックなど)。

于 2014-11-16T12:26:34.923 に答える
-2

jvmtiEventCallbacks のイベントはどれも適切に見えません (DataDumpRequestion を使用したい場合を除きますが、使用する場合はここで質問する必要はありません:ok。これまでのところ、jvm にアタッチした方法はほとんど同じです (わずかな違いはあります))。コールバックからではない場合、GetStackTrace を呼び出すために、jvmtiEnv へのポインターを取得するにはどうすればよいでしょうか? ポイントは、t を呼び出すことです。

于 2014-11-17T01:23:23.800 に答える