jstack -F 如何影响正在运行的 Java 进程?
我试图诊断一个问题,我正在使用的Java Web应用程序(Jenkins)变得无响应。如果我在没有标志的情况下运行,它不会给我任何东西,但是如果我把标志放进去强制线程转储,我不仅会得到一个结果,而且应用程序开始响应并继续,就好像什么都没发生一样,直到它最终停止再次响应。jstack
-F
标志会影响正在运行的 JVM 并导致无响应的应用程序再次开始响应,这有什么作用?jstack -F
我试图诊断一个问题,我正在使用的Java Web应用程序(Jenkins)变得无响应。如果我在没有标志的情况下运行,它不会给我任何东西,但是如果我把标志放进去强制线程转储,我不仅会得到一个结果,而且应用程序开始响应并继续,就好像什么都没发生一样,直到它最终停止再次响应。jstack
-F
标志会影响正在运行的 JVM 并导致无响应的应用程序再次开始响应,这有什么作用?jstack -F
您可以在此处查看要 jstack 的源代码。-F 参数更改了 jstack 连接到 jvm 的方式。使用 -F(或 -m)JStack 使用 java 调试器接口连接到 jvm。如果指定了 pid,JStack 将与 SA PID 连接连接器连接,该连接器显示:
要调试的进程不需要在调试模式下启动(即,使用 -agentlib:jdwp 或 -Xrunjdwp)。允许挂起进程。
我不知道为什么它会导致无响应的应用程序再次开始响应,但上面的链接也说,
当此连接器连接时,该过程将暂停,当此连接器分离时,该过程将恢复。
这可能会产生影响。
jstack -F -l pid 类似于(假设工作 dir 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 线程。如果应用程序因线程匮乏而挂起,则挂起方法调用可能会放宽它们。