Как jstack -F влияет на запущенный процесс Java?

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

Что делает флаг jstack -F, что повлияет на работающую JVM и заставит не отвечающее приложение снова начать отвечать?


person Jordan Bentley    schedule 21.08.2012    source источник
comment
Просто предположение, но это может вызвать ложное пробуждение или что-то подобное.   -  person Jeffrey    schedule 22.08.2012
comment
Чтобы установить причину проблемы, я бы попробовал использовать jdb. Таким образом, когда приложение не отвечает, вы сможете подключиться и выяснить причину.   -  person dan    schedule 31.08.2012


Ответы (2)


Вы можете увидеть исходный код jstack здесь. Аргумент -F изменяет способ подключения jstack к jvm. С помощью -F (или -m) JStack подключается к jvm, используя интерфейс отладчика java. Если pid указан, JStack подключается к SA. Соединитель подключения PID, в котором говорится:

Отлаживаемый процесс не обязательно должен запускаться в режиме отладки (т. е. с -agentlib:jdwp или -Xrunjdwp). Допустимо зависание процесса.

Я не знаю, почему это может привести к тому, что не отвечающее приложение снова начнет отвечать, но ссылка выше также говорит:

Процесс приостанавливается, когда этот соединитель подключается, и возобновляется, когда этот соединитель отсоединяется.

Это может иметь эффект.

person sbridges    schedule 26.08.2012
comment
Механизм присоединения PID не требует совместной работы проверяемого процесса — он просто проверяет структуры памяти и пытается выяснить, что доступно. Он может предоставить меньше информации, чем если бы его хорошо спросили. - person ddimitrov; 26.08.2012
comment
хорошо, понял, почему он может работать лучше после jstack -F. - person BendaThierry.com; 27.08.2012
comment
Что изменится после приостановки и пробуждения процесса, что заставит приложение снова реагировать? - person Jordan Bentley; 31.08.2012
comment
@JordanBentley Трудно понять, почему, не зная, почему приложение вообще не отвечает. Это сборка, подкачка, сама машина перегружена? - person sbridges; 01.09.2012
comment
@sbridges В большинстве случаев, когда я запускаю на нем jmap -heap, когда он не отвечает, он показывает, что пространство eden заполнено, поэтому я предполагаю, что идет сборка мусора. Я включил одновременный GC, но это не имело никакого значения. Машина не могла быть перегружена, это мощный сервер, на котором не работает ничего, кроме Jenkins, и проблема все еще возникает, когда на нем нет запущенных сборок. Моим следующим шагом будет попробовать другую JVM, но мне все же хотелось бы знать, как приостановка процесса jstack изменит его выполнение для моего собственного любопытства. - person Jordan Bentley; 04.09.2012

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

и в солнце .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

Может быть, ниже кода волшебство

       jvmdi = new ServiceabilityAgentJVMDIModule(debugger, saLibNames);
       if (jvmdi.canAttach()) {
           jvmdi.attach();
           jvmdi.setCommandTimeout(6000);
           debugPrintln("Attached to Serviceability Agent's JVMDI module.");
           // Jog VM to suspended point with JVMDI module
           resume();
           suspendJava();
           suspend();
           debugPrintln("Suspended all Java threads.");
       }

он приостановит все потоки Java в целевом процессе. если ваше приложение зависает из-за голодания потоков, вызов метода suspend может их расслабить.

person Ted Shaw    schedule 29.08.2012