我正在尝试诊断一个问题,即我正在使用的Java Web应用程序 (Jenkins) 变得无响应。 如果我不带-F
标志运行 jstack
,它不会给我任何结果,但如果我加上 -F 标志来强制进行线程转储,则不仅会得到结果,而且该应用程序开始响应并继续运行,直到最终再次停止响应。
jstack -F
标志会对正在运行的JVM产生何种影响,导致一个不响应的应用程序重新开始响应呢?
我正在尝试诊断一个问题,即我正在使用的Java Web应用程序 (Jenkins) 变得无响应。 如果我不带-F
标志运行 jstack
,它不会给我任何结果,但如果我加上 -F 标志来强制进行线程转储,则不仅会得到结果,而且该应用程序开始响应并继续运行,直到最终再次停止响应。
jstack -F
标志会对正在运行的JVM产生何种影响,导致一个不响应的应用程序重新开始响应呢?
需要调试的进程不需要以调试模式启动(即使用-agentlib:jdwp或-Xrunjdwp)。 进程可以是挂起状态。
我不知道为什么它会导致无响应的应用程序开始重新响应,但上面的链接也说:
当此连接器附加时,进程被暂停,当此连接器分离时,进程恢复。
这可能会产生影响。
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代码中。
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方法可能会缓解这种情况。