2014-11-07 5 views
8

Существует несколько способов генерации дампов потоков в java.Есть ли способ генерации периодического дампа потока java с использованием JVMTI?

Я бы хотел использовать JVMTI (C API) для его создания, чтобы оценить влияние его производительности на работающую JVM. (Я знаю jstack и JMX, этот вопрос обычно не связан с дампами потоков, а об использовании JVMTI API).

Я основываю свой код на this blog post. Там java-агент подключается к сигналу SIGQUIT. Я бы хотел этого избежать, потому что это тот же сигнал, что и JVM для записи дампа потока в stdout. Я хочу избежать этой двуличности.

Другими словами, я хотел бы либо подключиться к другому сигналу, либо найти способ для агента периодически генерировать дамп потока.

+0

Ни одно из событий в jvmtiEventCallbacks не подходит (если вы не хотите использовать DataDumpRequestion, но если вы это сделали, вы не спрашивали здесь :)). Похоже, вам лучше всего позвонить своему агенту прямо в GetStackTrace. Есть ли причина, по которой вы не можете этого сделать? –

+0

@ Paul-Hicks, Не могли бы вы разместить ссылку или код о том, как я буду прикреплять к jvm в этом случае? – Ovesh

+0

Вы помещаете dll агента или .so в ваш -ventpath вашего jvm или определяете его как -agentlib. Взгляните на [этот ответ] (http://stackoverflow.com/a/173447/3195526) или [вводная страница IBM] (http://publib.boulder.ibm.com/infocenter/realtime/v2r0/index. JSP? тема =% 2Fcom.ibm.rt.doc.20% 2Fdiag% 2Ftools% 2Fjvmti.html). Это то, что вы хотели знать? Должен ли я превратить это в ответ? –

ответ

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

Я хотел бы либо прикрепить к другому сигналу

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"); 

причины вы можете написать полностью родной обработчик сигнала сигнала (обратите внимание, что я не проверял, это только идея, которая должна работать)

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 оттуда в любое время вы хотите (обратные вызовы таймера и т.д.)

+0

Получает '* jvmti' из' * gdata' сейф? Я не уверен в этом, но я могу попробовать. – Ovesh

+1

Это должно быть безопасно. По крайней мере, вы всегда можете использовать [RawMonitorEnter] (https://docs.oracle.com/javase/7/docs/platform/jvmti/jvmti.html#RawMonitorEnter) и [RawMonitorExit] (https://docs.oracle.com /javase/7/docs/platform/jvmti/jvmti.html#RawMonitorExit) с gdata-> lock, но я не думаю, что это действительно необходимо, пока вы не будете одновременно обращаться к gdata-> jvmti. – szhem

+1

Также вы можете создать поток с помощью [RunAgentThread] (https://docs.oracle.com/javase/7/docs/platform/jvmti/jvmti.html#RunAgentThread). [Start function] (https://docs.oracle.com/javase/7/docs/platform/jvmti/jvmti.html#jvmtiStartFunction) принимает jvmtiEnv как свой первый параметр. Таким образом, вы можете делать периодические дампы потоков изнутри этого созданного потока. – szhem

-2

None событий в jvmtiEventCallbacks выглядят подходящими (если вы не хотите использовать DataDumpRequestion, но если бы вы это сделали, вы бы не спрашивали здесь: хорошо, так что это почти так же, как я привязался к jvm до сих пор (с незначительными отличиями). Поэтому, я думаю, это подводит меня к следующему вопросу: как мне получить inter to jvmtiEnv, чтобы вызвать GetStackTrace, если не от обратного вызова? Дело в том, чтобы назвать Т

2

Если ваша цель состоит в том, чтобы периодически собирать нити дамп, вы можете использовать Java Flight Recorder, которая является частью Java Mission Controller

Начиная с выпуском Oracle JDK 7 Update 40 (7u40), Java Mission Control поставляется вместе с JVM HotSpot.

0

Запись в блоге, которую вы цитируете, имеет большую часть того, что вам нужно для сантехники JVMTI. Вы можете использовать JVMTIenv из gdata. Это законно. Убедитесь, что вы делаете вызовы JNI для правильного JNIenv для вашего текущего потока.

Теперь вам нужно добавить способ получения уведомления о принятии вашего действия (например, дамп потока). Открутите поток, который прослушивает сокет, использует inotify, семафоры и т. Д. - то, что вы можете выталкивать извне.

Затем вы можете вызвать dumpThreadInfo() из цикла обработчика событий, как вы считаете нужным.

 Смежные вопросы

  • Нет связанных вопросов^_^