Как jstack -F влияет на запущенный Java-процесс?
Я пытаюсь диагностировать проблему, когда веб-приложение Java, которое я использую (Jenkins), перестает реагировать. Если я запустил jstack
без флага -F
, это ничего мне не даст, но если я поставлю флаг для принудительного дампа потока, я получаю не только результат, но приложение начинает отвечать и продолжается, как если бы ничего не случилось, пока он не перестанет отвечать снова.
Что означает флаг jstack -F
, который повлияет на запущенную JVM и заставит невосприимчивое приложение снова отвечать на запросы?
Ответы
Ответ 1
Вы можете увидеть источник в jstack здесь. Аргумент -F изменяет способ подключения jstm к jvm. С -F (или -m) JStack подключается к jvm с помощью интерфейса java debugger. Если указан pid, JStack соединяется с SA PID Attaching Connector, который гласит:
Отлаживаемый процесс не должен запускаться в отладке (т.е. с -agentlib: jdwp или -Xrunjdwp). Это допустимо для > .
Я не знаю, почему это приведет к тому, что невосприимчивое приложение начнет отвечать на запросы снова, но ссылка выше также говорит:
Процесс приостанавливается, когда этот соединитель присоединяется и возобновляется, когда этот разъем отсоединяется.
Это может иметь эффект.
Ответ 2
jstack -F -l pid аналогичен (предполагается, что рабочий каталог JAVA_HOME)
bin/java -Dsun.jvm.hotspot.debugger.useWindbgDebugger -Dsun.jvm.hotspot.debugger.useProcDebugger -cp lib/sa-jdi.jar;lib/tools.jar sun.tools.jstack.JStack -F -l pid
и в sun.tools.jstack.JStack code
if (arg.equals("-F")) {
useSA = true;
}
.....
// now execute using the SA JStack tool or the built-in thread dumper
if (useSA) {
// parameters (<pid> or <exe> <core>
...
runJStackTool(mixed, locks, params);
} else {
// pass -l to thread dump operation to get extra lock info
String pid = args[optionCount];
...
runThreadDump(pid, params);
}
а так как -F передается, runJStackTool вызывается для загрузки sun.jvm.hotspot.tools.JStack, он имеет тот же эффект прямого вызова
bin\java -Dsun.jvm.hotspot.debugger.useWindbgDebugger -Dsun.jvm.hotspot.debugger.useProcDebugger -cp lib/sa-jdi.jar;lib/tools.jar sun.jvm.hotspot.tools.JStack pid
и sun.jvm.hotspot.tools.JStack будет вызывать sun.jvm.hotspot.bugspot.BugSpotAgent attach → go → setupVM method
Возможно, ниже кода магия
jvmdi = new ServiceabilityAgentJVMDIModule(debugger, saLibNames);
if (jvmdi.canAttach()) {
jvmdi.attach();
jvmdi.setCommandTimeout(6000);
debugPrintln("Attached to Serviceability Agent JVMDI module.");
// Jog VM to suspended point with JVMDI module
resume();
suspendJava();
suspend();
debugPrintln("Suspended all Java threads.");
}
он приостанавливает все потоки Java в целевом процессе. если ваше приложение зависает для голодания нити, вызов метода suspend может ослабить их.