【问题标题】:How does jstack -F affect a running Java process?jstack -F 如何影响正在运行的 Java 进程?
【发布时间】:2012-08-21 18:53:18
【问题描述】:

我正在尝试诊断我正在使用的 Java Web 应用程序 (Jenkins) 变得无响应的问题。如果我在没有-F 标志的情况下运行jstack,它不会给我任何东西,但如果我将标志放入强制线程转储,我不仅会得到结果,而且应用程序开始响应并继续运行,就好像在它最终再次停止响应之前什么都没有发生。

jstack -F 标志做了什么会影响正在运行的 JVM 并导致无响应的应用程序再次开始响应?

【问题讨论】:

  • 只是推测,但它可能会导致虚假唤醒或类似的事情发生。
  • 为了确定导致问题的原因,我会尝试使用 jdb。这样,当应用程序无响应时,您将能够附加并调查原因。

标签: java jvm jstack


【解决方案1】:

你可以看到 jstack here 的源代码。 -F 参数改变 jstack 连接到 jvm 的方式。使用 -F(或 -m),JStack 使用 java 调试器接口连接到 jvm。如果指定了 pid,JStack 将与 SA PID Attaching Connector 连接,它表示,

要调试的进程不必在调试中启动 模式(即,使用 -agentlib:jdwp 或 -Xrunjdwp)。这是允许的 要挂起的进程。

我不知道为什么它会导致无响应的应用程序再次开始响应,但上面的链接也说,

当这个连接器连接时进程被挂起,当这个连接器连接时进程被恢复 此连接器分离。

这可能会产生影响。

【讨论】:

  • PID 附加机制不需要被检查的进程进行协作——它只是检查内存结构并尝试找出可用的内容。如果问得好,它可能会提供更少的信息。
  • ok 已经明白为什么在 jstack -F 之后它可以更好地工作了。
  • 进程暂停和唤醒后会发生什么变化,从而导致应用程序再次响应?
  • @JordanBentley 如果不知道为什么应用程序一开始就没有响应,就很难知道为什么。是gc'ing,换掉,机器本身超载了吗?
  • @sbridges 大多数时候,当我在它上面运行 jmap -heap 时它没有响应,它会显示伊甸园空间已满,所以我假设 GC 正在进行。我打开了并发 GC,但这没有任何区别。这台机器不能超载,它是一个强大的服务器,除了 Jenkins 之外没有其他任何东西在上面运行,当它下面没有运行任何构建时,问题仍然存在。我的下一步将是尝试不同的 JVM,但我仍然想知道 jstack 暂停进程会如何改变它的执行,以满足我自己的好奇心。
【解决方案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 方法

也许下面的代码很神奇

       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 线程。如果您的应用程序因线程饥饿而挂起,则挂起方法调用可能会放松它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-17
    • 2013-09-10
    • 1970-01-01
    • 1970-01-01
    • 2019-08-08
    相关资源
    最近更新 更多