Как правильно написать обработчик SIGPROF, который вызывает AsyncGetCallTrace? - PullRequest
3 голосов
/ 06 августа 2010

Я пишу короткий и простой профилировщик (на C), который предназначен для регулярной печати распечатки трасс стека для потоков в различных клиентах Java.Я должен использовать недокументированную функцию AsyncGetCallTrace вместо GetStackTrace, чтобы минимизировать вторжение и разрешить трассировку стека независимо от состояния потока.Исходный код функции можно найти здесь: http://download.java.net/openjdk/jdk6/promoted/b20/openjdk-6-src-b20-21_jun_2010.tar.gz в hotspot / src / share / vm / prims / forte.cpp.Я нашел несколько справочных страниц, описывающих JVMTI, обработку сигналов и синхронизацию, а также блог с подробностями о том, как настроить вызов AsyncGetCallTrace: http: // jeremymanson.blogspot.com/2007/05/profiling-with-jvmtijvmpi-sigprof-and.html.

В этом блоге отсутствует код для фактического вызова функции в обработчике сигналов (автор предполагает, что читатель может сделать это самостоятельно).Я прошу помощи в выполнении именно этого.Я не уверен, как и где создать struct ASGCT_CallTrace (и внутреннюю структуру ASGCT_CallFrame), как определено в вышеупомянутом файле forte.cpp.Структура ASGCT_CallTrace является одним из параметров, передаваемых AsyncGetCallTrace, поэтому мне нужно его создать, но я не знаю, как получить правильные значения для его полей: JNIEnv * env_id, jint num_frames и JVMPI_CallFrame frames.Кроме того, я не знаю, каким должен быть третий параметр, переданный AsyncGetCallTrace (void ucontext)?

Вышеприведенная проблема является основной, которую я имею.Однако есть и другие проблемы, с которыми я сталкиваюсь: [1] SIGPROF, похоже, не вызывается таймером точно через указанные интервалы, а, скорее, немного реже.То есть, если я установлю таймер на отправку SIGPROF каждую секунду (1 секунда, 0 секунд), то за 5 секунд я получу менее 5 выходов обработчика SIGPROF (обычно 1-3) [2] Выход обработчика SIGPROFвообще не появляются во время Thread.sleep в коде Java.Итак, если SIGPROF должен отправляться каждую секунду, и у меня есть Thread.sleep (5000);, я не получу никаких выходных данных обработчика во время выполнения этого кода.

Любая помощь будет принята с благодарностью.Дополнительные детали (а также части кода и примеры выходных данных) будут опубликованы по запросу.

Спасибо!

1 Ответ

1 голос
/ 10 августа 2010

Я наконец-то получил положительный результат, но поскольку здесь возникло небольшое обсуждение, мой собственный ответ будет кратким.

Структура ASGCT_CallTrace (и базовый массив ASGCT_CallFrame) можно просто объявить в обработчике сигналов,при этом существует только стек: ASGCT_CallTrace trace;JNIEnv * env;global_VM_pointer-> AttachCurrentThread ((void **) & env, NULL);trace.env_id = env;trace.num_frames = 0;Хранилище ASGCT_CallFrame [25];trace.frames = storage;

Следующее получает uContext: ucontext_t uContext;getcontext (& uContext);

И тогда вызов просто: AsyncGetCallTrace (& trace, 25, & uContext);

Я уверен, что есть некоторые другие нюансы, о которых мне нужно было позаботиться впроцесс, но я действительно не документировал их.Я не уверен, что могу раскрыть полный текущий код, который у меня есть, который успешно асинхронно запрашивает и получает следы стека любой Java-программы через фиксированные интервалы.Но если кто-то заинтересован или застрял в той же проблеме, я теперь могу помочь (я думаю).

По двум другим вопросам: [1] Если поток спит и генерируется SIGPROF,поток обрабатывает этот сигнал только после пробуждения.Это нормально, так как поток обрабатывает сигнал.[2] Кажется, что недостатки таймера больше не появляются.Возможно, я неправильно измерил.

...